diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 4528766676137ec8b7b84c5a21380fa11328d2b0..38ced5d717bd1eabf527d5d7c956c9868097eb9d 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -58,7 +58,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { uint16_t db_fulllength, db_halflength; int slotoffsetF=0, blockoffsetF=0; - uint16_t *data_block=NULL, *i=NULL; + uint16_t *data_block=NULL, *i=NULL, *d=NULL; IF4p5_header_t *packet_header=NULL; eth_state_t *eth = (eth_state_t*) (ru->ifdevice.priv); @@ -138,23 +138,48 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { if (packet_type == IF4p5_PULFFT) { + uint16_t *rx0 = (uint16_t*) &rxdataF[0][blockoffsetF]; + uint16_t *rx1 = (uint16_t*) &rxdataF[0][slotoffsetF]; + + for (symbol_id=fp->symbols_per_tti-nsym; symbol_id<fp->symbols_per_tti; symbol_id++) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF4_SYMBOL, symbol_id ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); - for (element_id=0; element_id<db_halflength; element_id++) { - i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; - data_block[element_id] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8)); - - i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id]; - data_block[element_id+db_halflength] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8)); - //if (element_id==0) LOG_I(PHY,"send_if4p5: symbol %d rxdata0 = (%d,%d)\n",symbol_id,*i,*(i+1)); - - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); - packet_header->frame_status &= ~(0x000f<<26); - packet_header->frame_status |= (symbol_id&0x000f)<<26; + + start_meas(&ru->compression); + + for (element_id=0; element_id<db_halflength; element_id+=8) { + i = (uint16_t*) &rx0[element_id]; + d = (uint16_t*) &data_block[element_id]; + d[0] = ((uint16_t) lin2alaw_if4p5[i[0]]) | ((uint16_t)(lin2alaw_if4p5[i[1]]<<8)); + d[1] = ((uint16_t) lin2alaw_if4p5[i[2]]) | ((uint16_t)(lin2alaw_if4p5[i[3]]<<8)); + d[2] = ((uint16_t) lin2alaw_if4p5[i[4]]) | ((uint16_t)(lin2alaw_if4p5[i[5]]<<8)); + d[3] = ((uint16_t) lin2alaw_if4p5[i[6]]) | ((uint16_t)(lin2alaw_if4p5[i[7]]<<8)); + d[4] = ((uint16_t) lin2alaw_if4p5[i[8]]) | ((uint16_t)(lin2alaw_if4p5[i[9]]<<8)); + d[5] = ((uint16_t) lin2alaw_if4p5[i[10]]) | ((uint16_t)(lin2alaw_if4p5[i[11]]<<8)); + d[6] = ((uint16_t) lin2alaw_if4p5[i[12]]) | ((uint16_t)(lin2alaw_if4p5[i[13]]<<8)); + d[7] = ((uint16_t) lin2alaw_if4p5[i[14]]) | ((uint16_t)(lin2alaw_if4p5[i[15]]<<8)); + + i = (uint16_t*) &rx1[element_id]; + d = (uint16_t*) &data_block[element_id+db_halflength]; + d[0] = ((uint16_t) lin2alaw_if4p5[i[0]]) | ((uint16_t)(lin2alaw_if4p5[i[1]]<<8)); + d[1] = ((uint16_t) lin2alaw_if4p5[i[2]]) | ((uint16_t)(lin2alaw_if4p5[i[3]]<<8)); + d[2] = ((uint16_t) lin2alaw_if4p5[i[4]]) | ((uint16_t)(lin2alaw_if4p5[i[5]]<<8)); + d[3] = ((uint16_t) lin2alaw_if4p5[i[6]]) | ((uint16_t)(lin2alaw_if4p5[i[7]]<<8)); + d[4] = ((uint16_t) lin2alaw_if4p5[i[8]]) | ((uint16_t)(lin2alaw_if4p5[i[9]]<<8)); + d[5] = ((uint16_t) lin2alaw_if4p5[i[10]]) | ((uint16_t)(lin2alaw_if4p5[i[11]]<<8)); + d[6] = ((uint16_t) lin2alaw_if4p5[i[12]]) | ((uint16_t)(lin2alaw_if4p5[i[13]]<<8)); + d[7] = ((uint16_t) lin2alaw_if4p5[i[14]]) | ((uint16_t)(lin2alaw_if4p5[i[15]]<<8)); + + } + + stop_meas(&ru->compression); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); + packet_header->frame_status &= ~(0x000f<<26); + packet_header->frame_status |= (symbol_id&0x000f)<<26; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); + start_meas(&ru->transport); if ((ru->ifdevice.trx_write_func(&ru->ifdevice, symbol_id, &tx_buffer, @@ -163,6 +188,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { IF4p5_PULFFT)) < 0) { perror("ETHERNET write for IF4p5_PULFFT\n"); } + stop_meas(&ru->transport); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; @@ -181,7 +207,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { } else if (packet_type >= IF4p5_PRACH && packet_type <= IF4p5_PRACH+4) { // FIX: hard coded prach samples length - LOG_D(PHY,"IF4p5_PRACH: frame %d, subframe %d\n",frame,subframe); + LOG_D(PHY,"IF4p5_PRACH: frame %d, subframe %d,packet type %x\n",frame,subframe,packet_type); db_fulllength = PRACH_NUM_SAMPLES; if (eth->flags == ETH_RAW_IF4p5_MODE) { @@ -222,6 +248,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { packet_type)) < 0) { perror("ETHERNET write for IF4p5_PRACH\n"); } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); } else { AssertFatal(1==0, "send_IF4p5 - Unknown packet_type %x", packet_type); @@ -283,7 +310,7 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint *subframe = ((packet_header->frame_status)>>22)&0x000f; *packet_type = packet_header->sub_type; - + LOG_D(PHY,"recv_IF4p5: Frame %d, Subframe %d: packet_type %x\n",*frame,*subframe,*packet_type); if (*packet_type == IF4p5_PDLFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL, *symbol_number ); @@ -313,7 +340,6 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size); blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 ); - if (ru->idx==0) LOG_D(PHY,"UL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",ru->idx,*frame,*subframe,*symbol_number); for (element_id=0; element_id<db_halflength; element_id++) { i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; *i = alaw2lin_if4p5[ (data_block[element_id] & 0xff) ]; @@ -353,8 +379,8 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint PRACH_BLOCK_SIZE_BYTES); } - //LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d => %d dB\n",ru->idx,*frame,*subframe, - // dB_fixed(signal_energy((int*)&prach_rxsigF[0][0],839))); + LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d => %d dB\n",ru->idx,*frame,*subframe, + dB_fixed(signal_energy((int*)&prach_rxsigF[0][0],839))); for (idx=0;idx<ru->num_eNB;idx++) ru->wakeup_prach_eNB(ru->eNB_list[idx],ru,*frame,*subframe); } else if (*packet_type == IF4p5_PULTICK) { diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index a251c62d0d16673dcbc8649d0392a3ce1d1afc99..0a95e60ead3c7af2bad4c55e73f742fc0308e4f1 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -39,11 +39,11 @@ #define IF4p5_PULFFT 0x0019 #define IF4p5_PDLFFT 0x0020 #define IF4p5_PRACH 0x0021 -#define IF4p5_PRACH_BR_CE0 0x0021 -#define IF4p5_PRACH_BR_CE1 0x0022 -#define IF4p5_PRACH_BR_CE2 0x0023 -#define IF4p5_PRACH_BR_CE3 0x0024 -#define IF4p5_PULTICK 0x0025 +#define IF4p5_PRACH_BR_CE0 0x0022 +#define IF4p5_PRACH_BR_CE1 0x0023 +#define IF4p5_PRACH_BR_CE2 0x0024 +#define IF4p5_PRACH_BR_CE3 0x0025 +#define IF4p5_PULTICK 0x0026 struct IF4p5_header { /// Type diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index dacafa6b290ddd0b1ab2682c67837a40facab4ae..c8da27bcb8cf3d60caf22f54e6c38f68750a3ffd 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -2169,8 +2169,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } //phase // stat_max *= nsymb; // normalize to energy per symbol -// stat_max /= (frame_parms->N_RB_UL*12); // +// stat_max /= (frame_parms->N_RB_UL*12); // stat_max /= (nsymb*12); + #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); #endif @@ -2308,7 +2309,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, // Do detection now #if defined(USRP_REC_PLAY) // It looks like the value is a bit messy when RF is replayed. - if (sigma2_dB<=(dB_fixed(stat_max)-pucch1_thres+2)) {// + // For instance i assume to skip pucch1_thres from the test below. + if (sigma2_dB<(dB_fixed(stat_max))) {// #else if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) {// #endif diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 24ea961b0e8240ff92163feb42dcb418760d3357..0e44a7f8bd6f184923f7798791b933422768fc7f 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -756,6 +756,10 @@ typedef struct RU_t_s{ time_stats_t rx_fhaul; /// Timing statistics (TX Fronthaul + Compression) time_stats_t tx_fhaul; + /// Timong statistics (Compression) + time_stats_t compression; + /// Timing statistics (Fronthaul transport) + time_stats_t transport; /// RX and TX buffers for precoder output RU_COMMON common; /// beamforming weight vectors per eNB diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 6d5ebae7d495793cfe261f6ff0a71c0db2c8c2e1..764c762f6a7da8bc2ca5f47521063a72040a6dfd 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -60,37 +60,37 @@ extern RAN_CONTEXT_t RC; /* sec 5.9, 36.321: MAC Reset Procedure */ -void ue_mac_reset(module_id_t module_idP,uint8_t eNB_index) +void ue_mac_reset(module_id_t module_idP, uint8_t eNB_index) { - //Resetting Bj - UE_mac_inst[module_idP].scheduling_info.Bj[0] = 0; - UE_mac_inst[module_idP].scheduling_info.Bj[1] = 0; - UE_mac_inst[module_idP].scheduling_info.Bj[2] = 0; + //Resetting Bj + UE_mac_inst[module_idP].scheduling_info.Bj[0] = 0; + UE_mac_inst[module_idP].scheduling_info.Bj[1] = 0; + UE_mac_inst[module_idP].scheduling_info.Bj[2] = 0; - //Stopping all timers + //Stopping all timers - //timeAlignmentTimer expires + //timeAlignmentTimer expires - // PHY changes for UE MAC reset - phy_reset_ue(module_idP,0,eNB_index); + // PHY changes for UE MAC reset + phy_reset_ue(module_idP, 0, eNB_index); - // notify RRC to relase PUCCH/SRS - // cancel all pending SRs - UE_mac_inst[module_idP].scheduling_info.SR_pending=0; - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0; + // notify RRC to relase PUCCH/SRS + // cancel all pending SRs + UE_mac_inst[module_idP].scheduling_info.SR_pending = 0; + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER = 0; //Set BSR Trigger Bmp and remove timer flags - UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; + UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; - // stop ongoing RACH procedure + // stop ongoing RACH procedure - // discard explicitly signaled ra_PreambleIndex and ra_RACH_MaskIndex, if any - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = 0; // check! - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; + // discard explicitly signaled ra_PreambleIndex and ra_RACH_MaskIndex, if any + UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = 0; // check! + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; - ue_init_mac(module_idP); //This will hopefully do the rest of the MAC reset procedure + ue_init_mac(module_idP); //This will hopefully do the rest of the MAC reset procedure } @@ -115,912 +115,1236 @@ typedef struct band_info_s { static const eutra_bandentry_t eutra_bandtable[] = { - { 1, 19200, 19800, 21100, 21700, 0}, - { 2, 18500, 19100, 19300, 19900, 6000}, - { 3, 17100, 17850, 18050, 18800, 12000}, - { 4, 17100, 17550, 21100, 21550, 19500}, - { 5, 8240, 8490, 8690, 8940, 24000}, - { 6, 8300, 8400, 8750, 8850, 26500}, - { 7, 25000, 25700, 26200, 26900, 27500}, - { 8, 8800, 9150 , 9250, 9600, 34500}, - { 9, 17499, 17849, 18449, 18799, 38000}, - {10, 17100, 17700, 21100, 21700, 41500}, - {11, 14279, 14529, 14759, 15009, 47500}, - {12, 6980, 7160, 7280, 7460, 50100}, - {13, 7770, 7870, 7460, 7560, 51800}, - {14, 7880, 7980, 7580, 7680, 52800}, - {17, 7040, 7160, 7340, 7460, 57300}, - {18, 8150, 9650, 8600, 10100, 58500}, - {19, 8300, 8450, 8750, 8900, 60000}, - {20, 8320, 8620, 7910, 8210, 61500}, - {21, 14479, 14629, 14959, 15109, 64500}, - {22, 34100, 34900, 35100, 35900, 66000}, - {23, 20000, 20200, 21800, 22000, 75000}, - {24, 16126, 16605, 15250, 15590, 77000}, - {25, 18500, 19150, 19300, 19950, 80400}, - {26, 8140 , 8490, 8590, 8940, 86900}, - {27, 8070 , 8240, 8520, 8690, 90400}, - {28, 7030 , 7580, 7580, 8130, 92100}, - {29, 0 , 0 , 7170, 7280, 96600}, - {30, 23050, 23250, 23500, 23600, 97700}, - {31, 45250, 34900, 46250, 35900, 98700}, - {32, 0 , 0 , 14520, 14960, 99200}, - {33, 19000, 19200, 19000, 19200, 36000}, - {34, 20100, 20250, 20100, 20250, 36200}, - {35, 18500, 19100, 18500, 19100, 36350}, - {36, 19300, 19900, 19300, 19900, 36950}, - {37, 19100, 19300, 19100, 19300, 37550}, - {38, 25700, 26200, 25700, 26300, 37750}, - {39, 18800, 19200, 18800, 19200, 38250}, - {40, 23000, 24000, 23000, 24000, 38650}, - {41, 24960, 26900, 24960, 26900, 39650}, - {42, 34000, 36000, 34000, 36000, 41590}, - {43, 36000, 38000, 36000, 38000, 43590}, - {44, 7030 , 8030, 7030, 8030, 45590}, - {45, 14470, 14670, 14470, 14670, 46590}, - {46, 51500, 59250, 51500, 59250, 46790}, - {65, 19200, 20100, 21100, 22000, 65536}, - {66, 17100, 18000, 21100, 22000, 66436}, - {67, 0 , 0 , 7380, 7580, 67336}, - {68, 6980 , 7280 , 7530, 7830, 67536}}; - -uint32_t to_earfcn(int eutra_bandP,uint32_t dl_CarrierFreq,uint32_t bw) { - - uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq/100000; - int bw_by_100 = bw/100; - - int i; - - AssertFatal(eutra_bandP < 69,"eutra_band %d > 68\n",eutra_bandP); - for (i=0;i<69 && eutra_bandtable[i].band!=eutra_bandP;i++); - - AssertFatal(dl_CarrierFreq_by_100k>=eutra_bandtable[i].dl_min, - "Band %d, bw %u : DL carrier frequency %u Hz < %u\n", - eutra_bandP,bw,dl_CarrierFreq,eutra_bandtable[i].dl_min); - AssertFatal(dl_CarrierFreq_by_100k<=(eutra_bandtable[i].dl_max-bw_by_100), - "Band %d, bw %u: DL carrier frequency %u Hz > %d\n", - eutra_bandP,bw,dl_CarrierFreq,eutra_bandtable[i].dl_max-bw_by_100); - - - return(dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min + (eutra_bandtable[i].N_OFFs_DL/10)); + {1, 19200, 19800, 21100, 21700, 0}, + {2, 18500, 19100, 19300, 19900, 6000}, + {3, 17100, 17850, 18050, 18800, 12000}, + {4, 17100, 17550, 21100, 21550, 19500}, + {5, 8240, 8490, 8690, 8940, 24000}, + {6, 8300, 8400, 8750, 8850, 26500}, + {7, 25000, 25700, 26200, 26900, 27500}, + {8, 8800, 9150, 9250, 9600, 34500}, + {9, 17499, 17849, 18449, 18799, 38000}, + {10, 17100, 17700, 21100, 21700, 41500}, + {11, 14279, 14529, 14759, 15009, 47500}, + {12, 6980, 7160, 7280, 7460, 50100}, + {13, 7770, 7870, 7460, 7560, 51800}, + {14, 7880, 7980, 7580, 7680, 52800}, + {17, 7040, 7160, 7340, 7460, 57300}, + {18, 8150, 9650, 8600, 10100, 58500}, + {19, 8300, 8450, 8750, 8900, 60000}, + {20, 8320, 8620, 7910, 8210, 61500}, + {21, 14479, 14629, 14959, 15109, 64500}, + {22, 34100, 34900, 35100, 35900, 66000}, + {23, 20000, 20200, 21800, 22000, 75000}, + {24, 16126, 16605, 15250, 15590, 77000}, + {25, 18500, 19150, 19300, 19950, 80400}, + {26, 8140, 8490, 8590, 8940, 86900}, + {27, 8070, 8240, 8520, 8690, 90400}, + {28, 7030, 7580, 7580, 8130, 92100}, + {29, 0, 0, 7170, 7280, 96600}, + {30, 23050, 23250, 23500, 23600, 97700}, + {31, 45250, 34900, 46250, 35900, 98700}, + {32, 0, 0, 14520, 14960, 99200}, + {33, 19000, 19200, 19000, 19200, 36000}, + {34, 20100, 20250, 20100, 20250, 36200}, + {35, 18500, 19100, 18500, 19100, 36350}, + {36, 19300, 19900, 19300, 19900, 36950}, + {37, 19100, 19300, 19100, 19300, 37550}, + {38, 25700, 26200, 25700, 26300, 37750}, + {39, 18800, 19200, 18800, 19200, 38250}, + {40, 23000, 24000, 23000, 24000, 38650}, + {41, 24960, 26900, 24960, 26900, 39650}, + {42, 34000, 36000, 34000, 36000, 41590}, + {43, 36000, 38000, 36000, 38000, 43590}, + {44, 7030, 8030, 7030, 8030, 45590}, + {45, 14470, 14670, 14470, 14670, 46590}, + {46, 51500, 59250, 51500, 59250, 46790}, + {65, 19200, 20100, 21100, 22000, 65536}, + {66, 17100, 18000, 21100, 22000, 66436}, + {67, 0, 0, 7380, 7580, 67336}, + {68, 6980, 7280, 7530, 7830, 67536} +}; + +uint32_t to_earfcn(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw) +{ + + uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq / 100000; + int bw_by_100 = bw / 100; + + int i; + + AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP); + for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++); + + AssertFatal(dl_CarrierFreq_by_100k >= eutra_bandtable[i].dl_min, + "Band %d, bw %u : DL carrier frequency %u Hz < %u\n", + eutra_bandP, bw, dl_CarrierFreq, + eutra_bandtable[i].dl_min); + AssertFatal(dl_CarrierFreq_by_100k <= + (eutra_bandtable[i].dl_max - bw_by_100), + "Band %d, bw %u: DL carrier frequency %u Hz > %d\n", + eutra_bandP, bw, dl_CarrierFreq, + eutra_bandtable[i].dl_max - bw_by_100); + + + return (dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min + + (eutra_bandtable[i].N_OFFs_DL / 10)); } -uint32_t from_earfcn(int eutra_bandP,uint32_t dl_earfcn) { +uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn) +{ - int i; + int i; - AssertFatal(eutra_bandP < 69,"eutra_band %d > 68\n",eutra_bandP); - for (i=0;i<69 && eutra_bandtable[i].band!=eutra_bandP;i++); + AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP); + for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++); - return(eutra_bandtable[i].dl_min + (dl_earfcn-(eutra_bandtable[i].N_OFFs_DL/10)))*100000; + return (eutra_bandtable[i].dl_min + + (dl_earfcn - (eutra_bandtable[i].N_OFFs_DL / 10))) * 100000; } -int32_t get_uldl_offset(int eutra_bandP) { - int i; +int32_t get_uldl_offset(int eutra_bandP) +{ + int i; - for (i=0;i<69 && eutra_bandtable[i].band!=eutra_bandP;i++); - return(eutra_bandtable[i].dl_min - eutra_bandtable[i].ul_min); + for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++); + return (eutra_bandtable[i].dl_min - eutra_bandtable[i].ul_min); } -uint32_t bw_table[6] = {6*180,15*180,25*180,50*180,75*180,100*180}; - -void config_mib(int Mod_idP, - int CC_idP, - int eutra_bandP, - int dl_BandwidthP, - PHICH_Config_t *phich_configP, - int Nid_cellP, - int NcpP, - int p_eNBP, - uint32_t dl_CarrierFreqP, - uint32_t ul_CarrierFreqP, - uint32_t pbch_repetitionP) { - - nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; - - cfg->subframe_config.pcfich_power_offset.value = 6000; // 0dB - cfg->subframe_config.dl_cyclic_prefix_type.value = NcpP; - cfg->subframe_config.ul_cyclic_prefix_type.value = NcpP; - - LOG_I(MAC,"Ncp %d,p_eNB %d\n",NcpP,p_eNBP); - - cfg->rf_config.dl_channel_bandwidth.value = dl_BandwidthP; - cfg->rf_config.ul_channel_bandwidth.value = dl_BandwidthP; - cfg->rf_config.tx_antenna_ports.value = p_eNBP; - cfg->rf_config.rx_antenna_ports.value = 2; - - cfg->nfapi_config.earfcn.value = to_earfcn(eutra_bandP,dl_CarrierFreqP,bw_table[dl_BandwidthP]/100); - cfg->nfapi_config.rf_bands.number_rf_bands = 1; - cfg->nfapi_config.rf_bands.rf_band[0] = eutra_bandP; - cfg->phich_config.phich_resource.value = phich_configP->phich_Resource; - cfg->phich_config.phich_duration.value = phich_configP->phich_Duration; - cfg->phich_config.phich_power_offset.value = 6000; // 0dB - - cfg->sch_config.primary_synchronization_signal_epre_eprers.value = 6000; // 0dB - cfg->sch_config.secondary_synchronization_signal_epre_eprers.value = 6000; // 0dB - cfg->sch_config.physical_cell_id.value = Nid_cellP; +uint32_t bw_table[6] = + { 6 * 180, 15 * 180, 25 * 180, 50 * 180, 75 * 180, 100 * 180 }; + +void +config_mib(int Mod_idP, + int CC_idP, + int eutra_bandP, + int dl_BandwidthP, + PHICH_Config_t * phich_configP, + int Nid_cellP, + int NcpP, + int p_eNBP, + uint32_t dl_CarrierFreqP, + uint32_t ul_CarrierFreqP, uint32_t pbch_repetitionP) +{ + + nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; + + cfg->subframe_config.pcfich_power_offset.value = 6000; // 0dB + cfg->subframe_config.dl_cyclic_prefix_type.value = NcpP; + cfg->subframe_config.ul_cyclic_prefix_type.value = NcpP; + + LOG_I(MAC, "Ncp %d,p_eNB %d\n", NcpP, p_eNBP); + + cfg->rf_config.dl_channel_bandwidth.value = dl_BandwidthP; + cfg->rf_config.ul_channel_bandwidth.value = dl_BandwidthP; + cfg->rf_config.tx_antenna_ports.value = p_eNBP; + cfg->rf_config.rx_antenna_ports.value = 2; + + cfg->nfapi_config.earfcn.value = + to_earfcn(eutra_bandP, dl_CarrierFreqP, + bw_table[dl_BandwidthP] / 100); + cfg->nfapi_config.rf_bands.number_rf_bands = 1; + cfg->nfapi_config.rf_bands.rf_band[0] = eutra_bandP; + cfg->phich_config.phich_resource.value = phich_configP->phich_Resource; + cfg->phich_config.phich_duration.value = phich_configP->phich_Duration; + cfg->phich_config.phich_power_offset.value = 6000; // 0dB + + cfg->sch_config.primary_synchronization_signal_epre_eprers.value = 6000; // 0dB + cfg->sch_config.secondary_synchronization_signal_epre_eprers.value = 6000; // 0dB + cfg->sch_config.physical_cell_id.value = Nid_cellP; #ifdef Rel14 - cfg->emtc_config.pbch_repetitions_enable_r13.value = pbch_repetitionP; -#endif + cfg->emtc_config.pbch_repetitions_enable_r13.value = pbch_repetitionP; +#endif } -void config_sib1(int Mod_idP, - int CC_idP, - TDD_Config_t *tdd_ConfigP) { +void config_sib1(int Mod_idP, int CC_idP, TDD_Config_t * tdd_ConfigP) +{ - nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; + nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; + + if (tdd_ConfigP) { //TDD + cfg->subframe_config.duplex_mode.value = 0; + cfg->tdd_frame_structure_config.subframe_assignment.value = + tdd_ConfigP->subframeAssignment; + cfg->tdd_frame_structure_config.special_subframe_patterns.value = + tdd_ConfigP->specialSubframePatterns; + } else { // FDD + cfg->subframe_config.duplex_mode.value = 1; + // Note no half-duplex here + } - if (tdd_ConfigP) { //TDD - cfg->subframe_config.duplex_mode.value = 0; - cfg->tdd_frame_structure_config.subframe_assignment.value = tdd_ConfigP->subframeAssignment; - cfg->tdd_frame_structure_config.special_subframe_patterns.value = tdd_ConfigP->specialSubframePatterns; - } - else { // FDD - cfg->subframe_config.duplex_mode.value = 1; - // Note no half-duplex here - } - } -int power_off_dB[6] = {78,118,140,170,188,200}; +int power_off_dB[6] = { 78, 118, 140, 170, 188, 200 }; -void config_sib2(int Mod_idP, - int CC_idP, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommonP, +void +config_sib2(int Mod_idP, + int CC_idP, + RadioResourceConfigCommonSIB_t * radioResourceConfigCommonP, #ifdef Rel14 - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BRP, + RadioResourceConfigCommonSIB_t * radioResourceConfigCommon_BRP, #endif - ARFCN_ValueEUTRA_t *ul_CArrierFreqP, - long *ul_BandwidthP, - AdditionalSpectrumEmission_t *additionalSpectrumEmissionP, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigListP) { - - nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; - - cfg->subframe_config.pb.value = radioResourceConfigCommonP->pdsch_ConfigCommon.p_b; - cfg->rf_config.reference_signal_power.value = radioResourceConfigCommonP->pdsch_ConfigCommon.referenceSignalPower; - cfg->nfapi_config.max_transmit_power.value = cfg->rf_config.reference_signal_power.value + power_off_dB[cfg->rf_config.dl_channel_bandwidth.value]; - - cfg->prach_config.configuration_index.value = radioResourceConfigCommonP->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - cfg->prach_config.root_sequence_index.value = radioResourceConfigCommonP->prach_Config.rootSequenceIndex; - cfg->prach_config.zero_correlation_zone_configuration.value = radioResourceConfigCommonP->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - cfg->prach_config.high_speed_flag.value = radioResourceConfigCommonP->prach_Config.prach_ConfigInfo.highSpeedFlag; - cfg->prach_config.frequency_offset.value = radioResourceConfigCommonP->prach_Config.prach_ConfigInfo.prach_FreqOffset; - - cfg->pusch_config.hopping_mode.value = radioResourceConfigCommonP->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - cfg->pusch_config.number_of_subbands.value = radioResourceConfigCommonP->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - cfg->pusch_config.hopping_offset.value = radioResourceConfigCommonP->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - - - - cfg->pucch_config.delta_pucch_shift.value = radioResourceConfigCommonP->pucch_ConfigCommon.deltaPUCCH_Shift; - cfg->pucch_config.n_cqi_rb.value = radioResourceConfigCommonP->pucch_ConfigCommon.nRB_CQI; - cfg->pucch_config.n_an_cs.value = radioResourceConfigCommonP->pucch_ConfigCommon.nCS_AN; - cfg->pucch_config.n1_pucch_an.value = radioResourceConfigCommonP->pucch_ConfigCommon.n1PUCCH_AN; - - if (radioResourceConfigCommonP->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled == true) - cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 1; - else if (radioResourceConfigCommonP->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled == true) - cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 2; - else // No hopping - cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 0; - - cfg->uplink_reference_signal_config.group_assignment.value = radioResourceConfigCommonP->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - cfg->uplink_reference_signal_config.cyclic_shift_1_for_drms.value = radioResourceConfigCommonP->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; - - // how to enable/disable SRS? - if (radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - cfg->srs_config.bandwidth_configuration.value = radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - cfg->srs_config.srs_subframe_configuration.value = radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - cfg->srs_config.srs_acknack_srs_simultaneous_transmission.value = radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; - - if (radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - cfg->srs_config.max_up_pts.value = 1; - else - cfg->srs_config.max_up_pts.value = 0; - } - -#ifdef Rel14 - if (RC.mac[Mod_idP]->common_channels[CC_idP].mib->message.schedulingInfoSIB1_BR_r13>0) { - AssertFatal(radioResourceConfigCommon_BRP!=NULL,"radioResource rou is missing\n"); - AssertFatal(radioResourceConfigCommon_BRP->ext4!=NULL,"ext4 is missing\n"); - cfg->emtc_config.prach_catm_root_sequence_index.value = radioResourceConfigCommon_BRP->prach_Config.rootSequenceIndex; - cfg->emtc_config.prach_catm_zero_correlation_zone_configuration.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - cfg->emtc_config.prach_catm_high_speed_flag.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.highSpeedFlag; - - struct PRACH_ConfigSIB_v1310 *ext4_prach=radioResourceConfigCommon_BRP->ext4->prach_ConfigCommon_v1310; - - PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; - - PRACH_ParametersCE_r13_t *p; - cfg->emtc_config.prach_ce_level_0_enable.value=0; - cfg->emtc_config.prach_ce_level_1_enable.value=0; - cfg->emtc_config.prach_ce_level_2_enable.value=0; - cfg->emtc_config.prach_ce_level_3_enable.value=0; - switch (prach_ParametersListCE_r13->list.count) { - case 4: - p=prach_ParametersListCE_r13->list.array[3]; - cfg->emtc_config.prach_ce_level_3_enable.value = 1; - cfg->emtc_config.prach_ce_level_3_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_3_frequency_offset.value = p->prach_FreqOffset_r13; - cfg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; - if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_3_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_3_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; - case 3: - p=prach_ParametersListCE_r13->list.array[2]; - cfg->emtc_config.prach_ce_level_2_enable.value = 1; - cfg->emtc_config.prach_ce_level_2_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_2_frequency_offset.value = p->prach_FreqOffset_r13; - cfg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; - if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_2_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_2_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; - case 2: - p=prach_ParametersListCE_r13->list.array[1]; - cfg->emtc_config.prach_ce_level_1_enable.value = 1; - cfg->emtc_config.prach_ce_level_1_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_1_frequency_offset.value = p->prach_FreqOffset_r13; - cfg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; - if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_1_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_1_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; - case 1: - p=prach_ParametersListCE_r13->list.array[0]; - cfg->emtc_config.prach_ce_level_0_enable.value = 1; - cfg->emtc_config.prach_ce_level_0_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_0_frequency_offset.value = p->prach_FreqOffset_r13; - cfg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; - if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_0_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_0_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; - } + ARFCN_ValueEUTRA_t * ul_CArrierFreqP, + long *ul_BandwidthP, + AdditionalSpectrumEmission_t * + additionalSpectrumEmissionP, + struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigListP) +{ - struct FreqHoppingParameters_r13 *ext4_freqHoppingParameters = radioResourceConfigCommonP->ext4->freqHoppingParameters_r13; - if ((ext4_freqHoppingParameters) && - (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13)){ - switch(ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13->present) { - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_NOTHING: /* No components present */ - break; - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_interval_FDD_r13: - cfg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea.value = ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13->choice.interval_FDD_r13; - break; - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_interval_TDD_r13: - cfg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea.value = ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13->choice.interval_TDD_r13; - break; - } + nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; + + cfg->subframe_config.pb.value = + radioResourceConfigCommonP->pdsch_ConfigCommon.p_b; + cfg->rf_config.reference_signal_power.value = + radioResourceConfigCommonP->pdsch_ConfigCommon. + referenceSignalPower; + cfg->nfapi_config.max_transmit_power.value = + cfg->rf_config.reference_signal_power.value + + power_off_dB[cfg->rf_config.dl_channel_bandwidth.value]; + + cfg->prach_config.configuration_index.value = + radioResourceConfigCommonP->prach_Config. + prach_ConfigInfo.prach_ConfigIndex; + cfg->prach_config.root_sequence_index.value = + radioResourceConfigCommonP->prach_Config.rootSequenceIndex; + cfg->prach_config.zero_correlation_zone_configuration.value = + radioResourceConfigCommonP->prach_Config. + prach_ConfigInfo.zeroCorrelationZoneConfig; + cfg->prach_config.high_speed_flag.value = + radioResourceConfigCommonP->prach_Config.prach_ConfigInfo. + highSpeedFlag; + cfg->prach_config.frequency_offset.value = + radioResourceConfigCommonP->prach_Config. + prach_ConfigInfo.prach_FreqOffset; + + cfg->pusch_config.hopping_mode.value = + radioResourceConfigCommonP->pusch_ConfigCommon. + pusch_ConfigBasic.hoppingMode; + cfg->pusch_config.number_of_subbands.value = + radioResourceConfigCommonP->pusch_ConfigCommon.pusch_ConfigBasic. + n_SB; + cfg->pusch_config.hopping_offset.value = + radioResourceConfigCommonP->pusch_ConfigCommon. + pusch_ConfigBasic.pusch_HoppingOffset; + + + + cfg->pucch_config.delta_pucch_shift.value = + radioResourceConfigCommonP->pucch_ConfigCommon.deltaPUCCH_Shift; + cfg->pucch_config.n_cqi_rb.value = + radioResourceConfigCommonP->pucch_ConfigCommon.nRB_CQI; + cfg->pucch_config.n_an_cs.value = + radioResourceConfigCommonP->pucch_ConfigCommon.nCS_AN; + cfg->pucch_config.n1_pucch_an.value = + radioResourceConfigCommonP->pucch_ConfigCommon.n1PUCCH_AN; + + if (radioResourceConfigCommonP-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled == + true) + cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 1; + else if (radioResourceConfigCommonP-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH. + sequenceHoppingEnabled == true) + cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 2; + else // No hopping + cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 0; + + cfg->uplink_reference_signal_config.group_assignment.value = + radioResourceConfigCommonP-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + cfg->uplink_reference_signal_config.cyclic_shift_1_for_drms.value = + radioResourceConfigCommonP-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; + + // how to enable/disable SRS? + if (radioResourceConfigCommonP->soundingRS_UL_ConfigCommon.present == + SoundingRS_UL_ConfigCommon_PR_setup) { + cfg->srs_config.bandwidth_configuration.value = + radioResourceConfigCommonP->soundingRS_UL_ConfigCommon. + choice.setup.srs_BandwidthConfig; + cfg->srs_config.srs_subframe_configuration.value = + radioResourceConfigCommonP->soundingRS_UL_ConfigCommon. + choice.setup.srs_SubframeConfig; + cfg->srs_config.srs_acknack_srs_simultaneous_transmission.value = + radioResourceConfigCommonP->soundingRS_UL_ConfigCommon. + choice.setup.ackNackSRS_SimultaneousTransmission; + + if (radioResourceConfigCommonP->soundingRS_UL_ConfigCommon. + choice.setup.srs_MaxUpPts) + cfg->srs_config.max_up_pts.value = 1; + else + cfg->srs_config.max_up_pts.value = 0; } - if ((ext4_freqHoppingParameters) && - (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13)){ - switch(ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13->present) { - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_NOTHING: /* No components present */ - break; - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_interval_FDD_r13: - cfg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb.value = ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13->choice.interval_FDD_r13; - break; - case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_interval_TDD_r13: - cfg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb.value = ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13->choice.interval_TDD_r13; - break; - } +#ifdef Rel14 + if (RC.mac[Mod_idP]->common_channels[CC_idP].mib-> + message.schedulingInfoSIB1_BR_r13 > 0) { + AssertFatal(radioResourceConfigCommon_BRP != NULL, + "radioResource rou is missing\n"); + AssertFatal(radioResourceConfigCommon_BRP->ext4 != NULL, + "ext4 is missing\n"); + cfg->emtc_config.prach_catm_root_sequence_index.value = + radioResourceConfigCommon_BRP->prach_Config.rootSequenceIndex; + cfg->emtc_config.prach_catm_zero_correlation_zone_configuration. + value = + radioResourceConfigCommon_BRP->prach_Config. + prach_ConfigInfo.zeroCorrelationZoneConfig; + cfg->emtc_config.prach_catm_high_speed_flag.value = + radioResourceConfigCommon_BRP->prach_Config. + prach_ConfigInfo.highSpeedFlag; + + struct PRACH_ConfigSIB_v1310 *ext4_prach = + radioResourceConfigCommon_BRP->ext4->prach_ConfigCommon_v1310; + + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = + &ext4_prach->prach_ParametersListCE_r13; + + PRACH_ParametersCE_r13_t *p; + cfg->emtc_config.prach_ce_level_0_enable.value = 0; + cfg->emtc_config.prach_ce_level_1_enable.value = 0; + cfg->emtc_config.prach_ce_level_2_enable.value = 0; + cfg->emtc_config.prach_ce_level_3_enable.value = 0; + switch (prach_ParametersListCE_r13->list.count) { + case 4: + p = prach_ParametersListCE_r13->list.array[3]; + cfg->emtc_config.prach_ce_level_3_enable.value = 1; + cfg->emtc_config.prach_ce_level_3_configuration_index.value = + p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_3_frequency_offset.value = + p->prach_FreqOffset_r13; + cfg-> + emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt. + value = p->numRepetitionPerPreambleAttempt_r13; + if (p->prach_StartingSubframe_r13) + cfg-> + emtc_config.prach_ce_level_3_starting_subframe_periodicity. + value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_3_hopping_enable.value = + p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_3_hopping_offset.value = + cfg->rf_config.ul_channel_bandwidth.value - 6; + case 3: + p = prach_ParametersListCE_r13->list.array[2]; + cfg->emtc_config.prach_ce_level_2_enable.value = 1; + cfg->emtc_config.prach_ce_level_2_configuration_index.value = + p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_2_frequency_offset.value = + p->prach_FreqOffset_r13; + cfg-> + emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt. + value = p->numRepetitionPerPreambleAttempt_r13; + if (p->prach_StartingSubframe_r13) + cfg-> + emtc_config.prach_ce_level_2_starting_subframe_periodicity. + value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_2_hopping_enable.value = + p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_2_hopping_offset.value = + cfg->rf_config.ul_channel_bandwidth.value - 6; + case 2: + p = prach_ParametersListCE_r13->list.array[1]; + cfg->emtc_config.prach_ce_level_1_enable.value = 1; + cfg->emtc_config.prach_ce_level_1_configuration_index.value = + p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_1_frequency_offset.value = + p->prach_FreqOffset_r13; + cfg-> + emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt. + value = p->numRepetitionPerPreambleAttempt_r13; + if (p->prach_StartingSubframe_r13) + cfg-> + emtc_config.prach_ce_level_1_starting_subframe_periodicity. + value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_1_hopping_enable.value = + p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_1_hopping_offset.value = + cfg->rf_config.ul_channel_bandwidth.value - 6; + case 1: + p = prach_ParametersListCE_r13->list.array[0]; + cfg->emtc_config.prach_ce_level_0_enable.value = 1; + cfg->emtc_config.prach_ce_level_0_configuration_index.value = + p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_0_frequency_offset.value = + p->prach_FreqOffset_r13; + cfg-> + emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt. + value = p->numRepetitionPerPreambleAttempt_r13; + if (p->prach_StartingSubframe_r13) + cfg-> + emtc_config.prach_ce_level_0_starting_subframe_periodicity. + value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_0_hopping_enable.value = + p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_0_hopping_offset.value = + cfg->rf_config.ul_channel_bandwidth.value - 6; + } + + struct FreqHoppingParameters_r13 *ext4_freqHoppingParameters = + radioResourceConfigCommonP->ext4->freqHoppingParameters_r13; + if ((ext4_freqHoppingParameters) + && + (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13)) + { + switch + (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13-> + present) { + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_NOTHING: /* No components present */ + break; + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_interval_FDD_r13: + cfg->emtc_config. + pucch_interval_ulhoppingconfigcommonmodea.value = + ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13-> + choice.interval_FDD_r13; + break; + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeA_r13_PR_interval_TDD_r13: + cfg->emtc_config. + pucch_interval_ulhoppingconfigcommonmodea.value = + ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeA_r13-> + choice.interval_TDD_r13; + break; + } + } + if ((ext4_freqHoppingParameters) && + (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13)) + { + switch + (ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13-> + present) { + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_NOTHING: /* No components present */ + break; + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_interval_FDD_r13: + cfg->emtc_config. + pucch_interval_ulhoppingconfigcommonmodeb.value = + ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13-> + choice.interval_FDD_r13; + break; + case FreqHoppingParameters_r13__interval_ULHoppingConfigCommonModeB_r13_PR_interval_TDD_r13: + cfg->emtc_config. + pucch_interval_ulhoppingconfigcommonmodeb.value = + ext4_freqHoppingParameters->interval_ULHoppingConfigCommonModeB_r13-> + choice.interval_TDD_r13; + break; + } + } } - } #endif } -void config_dedicated(int Mod_idP, - int CC_idP, - uint16_t rnti, - struct PhysicalConfigDedicated *physicalConfigDedicated) { +void +config_dedicated(int Mod_idP, + int CC_idP, + uint16_t rnti, + struct PhysicalConfigDedicated *physicalConfigDedicated) +{ } -void config_dedicated_scell(int Mod_idP, - uint16_t rnti, - SCellToAddMod_r10_t *sCellToAddMod_r10) { +void +config_dedicated_scell(int Mod_idP, + uint16_t rnti, + SCellToAddMod_r10_t * sCellToAddMod_r10) +{ } -int rrc_mac_config_req_eNB(module_id_t Mod_idP, - int CC_idP, - int physCellId, - int p_eNB, - int Ncp, - int eutra_band, - uint32_t dl_CarrierFreq, +int +rrc_mac_config_req_eNB(module_id_t Mod_idP, + int CC_idP, + int physCellId, + int p_eNB, + int Ncp, int eutra_band, uint32_t dl_CarrierFreq, #ifdef Rel14 - int pbch_repetition, + int pbch_repetition, #endif - rnti_t rntiP, - BCCH_BCH_Message_t *mib, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, + rnti_t rntiP, + BCCH_BCH_Message_t * mib, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon, #ifdef Rel14 - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon_BR, #endif - struct PhysicalConfigDedicated *physicalConfigDedicated, + struct PhysicalConfigDedicated + *physicalConfigDedicated, #if defined(Rel10) || defined(Rel14) - SCellToAddMod_r10_t *sCellToAddMod_r10, - //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, + SCellToAddMod_r10_t * sCellToAddMod_r10, + //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif - MeasObjectToAddMod_t **measObj, - MAC_MainConfig_t *mac_MainConfig, - long logicalChannelIdentity, - LogicalChannelConfig_t *logicalChannelConfig, - MeasGapConfig_t *measGapConfig, - TDD_Config_t *tdd_Config, - MobilityControlInfo_t *mobilityControlInfo, - SchedulingInfoList_t *schedulingInfoList, - uint32_t ul_CarrierFreq, - long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList + MeasObjectToAddMod_t ** measObj, + MAC_MainConfig_t * mac_MainConfig, + long logicalChannelIdentity, + LogicalChannelConfig_t * logicalChannelConfig, + MeasGapConfig_t * measGapConfig, + TDD_Config_t * tdd_Config, + MobilityControlInfo_t * mobilityControlInfo, + SchedulingInfoList_t * schedulingInfoList, + uint32_t ul_CarrierFreq, + long *ul_Bandwidth, + AdditionalSpectrumEmission_t * + additionalSpectrumEmission, + struct MBSFN_SubframeConfigList + *mbsfn_SubframeConfigList #if defined(Rel10) || defined(Rel14) - ,uint8_t MBMS_Flag, - MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, - PMCH_InfoList_r9_t *pmch_InfoList + , uint8_t MBMS_Flag, + MBSFN_AreaInfoList_r9_t * mbsfn_AreaInfoList, + PMCH_InfoList_r9_t * pmch_InfoList #endif #ifdef Rel14 - , - SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext + , + SystemInformationBlockType1_v1310_IEs_t * + sib1_v13ext #endif - ) { - - int i; - - int UE_id = -1; - eNB_MAC_INST *eNB = RC.mac[Mod_idP]; - UE_list_t *UE_list= &eNB->UE_list; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); - - - if (mib!=NULL) { - if (RC.mac == NULL) l2_init_eNB(); - - mac_top_init_eNB(); - - RC.mac[Mod_idP]->common_channels[CC_idP].mib = mib; - RC.mac[Mod_idP]->common_channels[CC_idP].physCellId = physCellId; - RC.mac[Mod_idP]->common_channels[CC_idP].p_eNB = p_eNB; - RC.mac[Mod_idP]->common_channels[CC_idP].Ncp = Ncp; - RC.mac[Mod_idP]->common_channels[CC_idP].eutra_band = eutra_band; - RC.mac[Mod_idP]->common_channels[CC_idP].dl_CarrierFreq = dl_CarrierFreq; - - LOG_I(MAC, - "Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u,phich_config.resource %d, phich_config.duration %d)\n", - Mod_idP, - CC_idP, - eutra_band, - to_prb((int)mib->message.dl_Bandwidth), - physCellId, - p_eNB, - dl_CarrierFreq, - (int)mib->message.phich_Config.phich_Resource, - (int)mib->message.phich_Config.phich_Duration); - - config_mib(Mod_idP,CC_idP, - eutra_band, - mib->message.dl_Bandwidth, - &mib->message.phich_Config, - physCellId, - Ncp, - p_eNB, - dl_CarrierFreq, - ul_CarrierFreq + ) +{ + + int i; + + int UE_id = -1; + eNB_MAC_INST *eNB = RC.mac[Mod_idP]; + UE_list_t *UE_list = &eNB->UE_list; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); + + + if (mib != NULL) { + if (RC.mac == NULL) + l2_init_eNB(); + + mac_top_init_eNB(); + + RC.mac[Mod_idP]->common_channels[CC_idP].mib = mib; + RC.mac[Mod_idP]->common_channels[CC_idP].physCellId = physCellId; + RC.mac[Mod_idP]->common_channels[CC_idP].p_eNB = p_eNB; + RC.mac[Mod_idP]->common_channels[CC_idP].Ncp = Ncp; + RC.mac[Mod_idP]->common_channels[CC_idP].eutra_band = eutra_band; + RC.mac[Mod_idP]->common_channels[CC_idP].dl_CarrierFreq = + dl_CarrierFreq; + + LOG_I(MAC, + "Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u,phich_config.resource %d, phich_config.duration %d)\n", + Mod_idP, + CC_idP, + eutra_band, + to_prb((int) mib->message.dl_Bandwidth), + physCellId, + p_eNB, + dl_CarrierFreq, + (int) mib->message.phich_Config.phich_Resource, + (int) mib->message.phich_Config.phich_Duration); + + config_mib(Mod_idP, CC_idP, + eutra_band, + mib->message.dl_Bandwidth, + &mib->message.phich_Config, + physCellId, Ncp, p_eNB, dl_CarrierFreq, ul_CarrierFreq #ifdef Rel14 - ,pbch_repetition + , pbch_repetition #endif - ); - - mac_init_cell_params(Mod_idP,CC_idP); - } - if (schedulingInfoList!=NULL) { - RC.mac[Mod_idP]->common_channels[CC_idP].tdd_Config = tdd_Config; - RC.mac[Mod_idP]->common_channels[CC_idP].schedulingInfoList = schedulingInfoList; - config_sib1(Mod_idP,CC_idP,tdd_Config); - } + ); + + mac_init_cell_params(Mod_idP, CC_idP); + } + if (schedulingInfoList != NULL) { + RC.mac[Mod_idP]->common_channels[CC_idP].tdd_Config = tdd_Config; + RC.mac[Mod_idP]->common_channels[CC_idP].schedulingInfoList = + schedulingInfoList; + config_sib1(Mod_idP, CC_idP, tdd_Config); + } #ifdef Rel14 - if (sib1_v13ext != NULL) { - RC.mac[Mod_idP]->common_channels[CC_idP].sib1_v13ext = sib1_v13ext; - } + if (sib1_v13ext != NULL) { + RC.mac[Mod_idP]->common_channels[CC_idP].sib1_v13ext = sib1_v13ext; + } #endif - if (radioResourceConfigCommon!=NULL) { - LOG_I(MAC,"[CONFIG]SIB2/3 Contents (partial)\n"); - LOG_I(MAC,"[CONFIG]pusch_config_common.n_SB = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB); - LOG_I(MAC,"[CONFIG]pusch_config_common.hoppingMode = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode); - LOG_I(MAC,"[CONFIG]pusch_config_common.pusch_HoppingOffset = %ld\n", radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset); - LOG_I(MAC,"[CONFIG]pusch_config_common.enable64QAM = %d\n",radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM); - LOG_I(MAC,"[CONFIG]pusch_config_common.groupHoppingEnabled = %d\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled); - LOG_I(MAC,"[CONFIG]pusch_config_common.groupAssignmentPUSCH = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH); - LOG_I(MAC,"[CONFIG]pusch_config_common.sequenceHoppingEnabled = %d\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled); - LOG_I(MAC,"[CONFIG]pusch_config_common.cyclicShift = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift); - - AssertFatal(radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx > 0, - "radioResourceconfigCommon %d == 0\n", - (int)radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx); - - RC.mac[Mod_idP]->common_channels[CC_idP].radioResourceConfigCommon = radioResourceConfigCommon; - if (ul_CarrierFreq>0) RC.mac[Mod_idP]->common_channels[CC_idP].ul_CarrierFreq = ul_CarrierFreq; - if (ul_Bandwidth) RC.mac[Mod_idP]->common_channels[CC_idP].ul_Bandwidth = *ul_Bandwidth; - else RC.mac[Mod_idP]->common_channels[CC_idP].ul_Bandwidth = RC.mac[Mod_idP]->common_channels[CC_idP].mib->message.dl_Bandwidth; - - config_sib2(Mod_idP, CC_idP, - radioResourceConfigCommon, + if (radioResourceConfigCommon != NULL) { + LOG_I(MAC, "[CONFIG]SIB2/3 Contents (partial)\n"); + LOG_I(MAC, "[CONFIG]pusch_config_common.n_SB = %ld\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.pusch_ConfigBasic.n_SB); + LOG_I(MAC, "[CONFIG]pusch_config_common.hoppingMode = %ld\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode); + LOG_I(MAC, + "[CONFIG]pusch_config_common.pusch_HoppingOffset = %ld\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset); + LOG_I(MAC, "[CONFIG]pusch_config_common.enable64QAM = %d\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM); + LOG_I(MAC, + "[CONFIG]pusch_config_common.groupHoppingEnabled = %d\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH. + groupHoppingEnabled); + LOG_I(MAC, + "[CONFIG]pusch_config_common.groupAssignmentPUSCH = %ld\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH. + groupAssignmentPUSCH); + LOG_I(MAC, + "[CONFIG]pusch_config_common.sequenceHoppingEnabled = %d\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH. + sequenceHoppingEnabled); + LOG_I(MAC, "[CONFIG]pusch_config_common.cyclicShift = %ld\n", + radioResourceConfigCommon-> + pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift); + + AssertFatal(radioResourceConfigCommon-> + rach_ConfigCommon.maxHARQ_Msg3Tx > 0, + "radioResourceconfigCommon %d == 0\n", + (int) radioResourceConfigCommon-> + rach_ConfigCommon.maxHARQ_Msg3Tx); + + RC.mac[Mod_idP]->common_channels[CC_idP]. + radioResourceConfigCommon = radioResourceConfigCommon; + if (ul_CarrierFreq > 0) + RC.mac[Mod_idP]->common_channels[CC_idP].ul_CarrierFreq = + ul_CarrierFreq; + if (ul_Bandwidth) + RC.mac[Mod_idP]->common_channels[CC_idP].ul_Bandwidth = + *ul_Bandwidth; + else + RC.mac[Mod_idP]->common_channels[CC_idP].ul_Bandwidth = + RC.mac[Mod_idP]->common_channels[CC_idP].mib->message. + dl_Bandwidth; + + config_sib2(Mod_idP, CC_idP, radioResourceConfigCommon, #ifdef Rel14 - radioResourceConfigCommon_BR, + radioResourceConfigCommon_BR, #endif - NULL, ul_Bandwidth, additionalSpectrumEmission, mbsfn_SubframeConfigList); + NULL, ul_Bandwidth, additionalSpectrumEmission, + mbsfn_SubframeConfigList); - } - - - // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup - if (logicalChannelConfig!= NULL) { // check for eMTC specific things - UE_id = find_UE_id(Mod_idP, rntiP); - - if (UE_id == -1) { - LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__); - } else { - if (logicalChannelConfig) - UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; - else - UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0; } - } - - - if (physicalConfigDedicated != NULL) { - UE_id = find_UE_id(Mod_idP, rntiP); + // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup + if (logicalChannelConfig != NULL) { // check for eMTC specific things + UE_id = find_UE_id(Mod_idP, rntiP); + + if (UE_id == -1) { + LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, + __LINE__, __FUNCTION__); + } else { + if (logicalChannelConfig) + UE_list-> + UE_template[CC_idP][UE_id].lcgidmap + [logicalChannelIdentity] = + *logicalChannelConfig-> + ul_SpecificParameters->logicalChannelGroup; + else + UE_list-> + UE_template[CC_idP][UE_id].lcgidmap + [logicalChannelIdentity] = 0; + } + } - if (UE_id == -1) - LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__); - else - UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated=physicalConfigDedicated; - } + if (physicalConfigDedicated != NULL) { + UE_id = find_UE_id(Mod_idP, rntiP); + if (UE_id == -1) + LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, + __LINE__, __FUNCTION__); + else + UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated = + physicalConfigDedicated; + } #if defined(Rel10) || defined(Rel14) - if (sCellToAddMod_r10 != NULL) { - UE_id = find_UE_id(Mod_idP, rntiP); - if (UE_id == -1) - LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__); - else - config_dedicated_scell(Mod_idP,rntiP,sCellToAddMod_r10); - - } + if (sCellToAddMod_r10 != NULL) { + UE_id = find_UE_id(Mod_idP, rntiP); + if (UE_id == -1) + LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, + __LINE__, __FUNCTION__); + else + config_dedicated_scell(Mod_idP, rntiP, sCellToAddMod_r10); + } #endif - if (mbsfn_SubframeConfigList != NULL) { - LOG_I(MAC,"[eNB %d][CONFIG] Received %d subframe allocation pattern for MBSFN\n", Mod_idP, mbsfn_SubframeConfigList->list.count); - RC.mac[Mod_idP]->common_channels[0].num_sf_allocation_pattern= mbsfn_SubframeConfigList->list.count; - - for (i=0; i<mbsfn_SubframeConfigList->list.count; i++) { - RC.mac[Mod_idP]->common_channels[0].mbsfn_SubframeConfig[i] = mbsfn_SubframeConfigList->list.array[i]; - LOG_I(MAC, "[eNB %d][CONFIG] MBSFN_SubframeConfig[%d] pattern is %x\n", Mod_idP, i, - RC.mac[Mod_idP]->common_channels[0].mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0]); - } - + if (mbsfn_SubframeConfigList != NULL) { + LOG_I(MAC, + "[eNB %d][CONFIG] Received %d subframe allocation pattern for MBSFN\n", + Mod_idP, mbsfn_SubframeConfigList->list.count); + RC.mac[Mod_idP]->common_channels[0].num_sf_allocation_pattern = + mbsfn_SubframeConfigList->list.count; + + for (i = 0; i < mbsfn_SubframeConfigList->list.count; i++) { + RC.mac[Mod_idP]->common_channels[0].mbsfn_SubframeConfig[i] = + mbsfn_SubframeConfigList->list.array[i]; + LOG_I(MAC, + "[eNB %d][CONFIG] MBSFN_SubframeConfig[%d] pattern is %x\n", + Mod_idP, i, + RC.mac[Mod_idP]-> + common_channels[0].mbsfn_SubframeConfig[i]-> + subframeAllocation.choice.oneFrame.buf[0]); + } + #ifdef Rel10 - RC.mac[Mod_idP]->common_channels[0].MBMS_flag = MBMS_Flag; + RC.mac[Mod_idP]->common_channels[0].MBMS_flag = MBMS_Flag; #endif - } - + } #if defined(Rel10) || defined(Rel14) - if (mbsfn_AreaInfoList != NULL) { - // One eNB could be part of multiple mbsfn syc area, this could change over time so reset each time - LOG_I(MAC,"[eNB %d][CONFIG] Received %d MBSFN Area Info\n", Mod_idP, mbsfn_AreaInfoList->list.count); - RC.mac[Mod_idP]->common_channels[0].num_active_mbsfn_area = mbsfn_AreaInfoList->list.count; - - for (i =0; i< mbsfn_AreaInfoList->list.count; i++) { - RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i] = mbsfn_AreaInfoList->list.array[i]; - LOG_I(MAC,"[eNB %d][CONFIG] MBSFN_AreaInfo[%d]: MCCH Repetition Period = %ld\n", Mod_idP,i, - RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9); - // config_sib13(Mod_idP,0,i,RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mbsfn_AreaId_r9); - } - } - - if (pmch_InfoList != NULL) { - - // LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9)); - - LOG_I(MAC, "[CONFIG] Number of PMCH in this MBSFN Area %d\n", pmch_InfoList->list.count); - - for (i =0; i< pmch_InfoList->list.count; i++) { - RC.mac[Mod_idP]->common_channels[0].pmch_Config[i] = &pmch_InfoList->list.array[i]->pmch_Config_r9; - - LOG_I(MAC, "[CONFIG] PMCH[%d]: This PMCH stop (sf_AllocEnd_r9) at subframe %ldth\n", i, - RC.mac[Mod_idP]->common_channels[0].pmch_Config[i]->sf_AllocEnd_r9); - LOG_I(MAC, "[CONFIG] PMCH[%d]: mch_Scheduling_Period = %ld\n", i, - RC.mac[Mod_idP]->common_channels[0].pmch_Config[i]->mch_SchedulingPeriod_r9); - LOG_I(MAC, "[CONFIG] PMCH[%d]: dataMCS = %ld\n", i, - RC.mac[Mod_idP]->common_channels[0].pmch_Config[i]->dataMCS_r9); - - // MBMS session info list in each MCH - RC.mac[Mod_idP]->common_channels[0].mbms_SessionList[i] = &pmch_InfoList->list.array[i]->mbms_SessionInfoList_r9; - LOG_I(MAC, "PMCH[%d] Number of session (MTCH) is: %d\n",i, RC.mac[Mod_idP]->common_channels[0].mbms_SessionList[i]->list.count); + if (mbsfn_AreaInfoList != NULL) { + // One eNB could be part of multiple mbsfn syc area, this could change over time so reset each time + LOG_I(MAC, "[eNB %d][CONFIG] Received %d MBSFN Area Info\n", + Mod_idP, mbsfn_AreaInfoList->list.count); + RC.mac[Mod_idP]->common_channels[0].num_active_mbsfn_area = + mbsfn_AreaInfoList->list.count; + + for (i = 0; i < mbsfn_AreaInfoList->list.count; i++) { + RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i] = + mbsfn_AreaInfoList->list.array[i]; + LOG_I(MAC, + "[eNB %d][CONFIG] MBSFN_AreaInfo[%d]: MCCH Repetition Period = %ld\n", + Mod_idP, i, + RC.mac[Mod_idP]->common_channels[0]. + mbsfn_AreaInfo[i]->mcch_Config_r9. + mcch_RepetitionPeriod_r9); + // config_sib13(Mod_idP,0,i,RC.mac[Mod_idP]->common_channels[0].mbsfn_AreaInfo[i]->mbsfn_AreaId_r9); + } } - } + if (pmch_InfoList != NULL) { + + // LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9)); + + LOG_I(MAC, "[CONFIG] Number of PMCH in this MBSFN Area %d\n", + pmch_InfoList->list.count); + + for (i = 0; i < pmch_InfoList->list.count; i++) { + RC.mac[Mod_idP]->common_channels[0].pmch_Config[i] = + &pmch_InfoList->list.array[i]->pmch_Config_r9; + + LOG_I(MAC, + "[CONFIG] PMCH[%d]: This PMCH stop (sf_AllocEnd_r9) at subframe %ldth\n", + i, + RC.mac[Mod_idP]->common_channels[0]. + pmch_Config[i]->sf_AllocEnd_r9); + LOG_I(MAC, "[CONFIG] PMCH[%d]: mch_Scheduling_Period = %ld\n", + i, + RC.mac[Mod_idP]->common_channels[0]. + pmch_Config[i]->mch_SchedulingPeriod_r9); + LOG_I(MAC, "[CONFIG] PMCH[%d]: dataMCS = %ld\n", i, + RC.mac[Mod_idP]->common_channels[0]. + pmch_Config[i]->dataMCS_r9); + + // MBMS session info list in each MCH + RC.mac[Mod_idP]->common_channels[0].mbms_SessionList[i] = + &pmch_InfoList->list.array[i]->mbms_SessionInfoList_r9; + LOG_I(MAC, "PMCH[%d] Number of session (MTCH) is: %d\n", i, + RC.mac[Mod_idP]->common_channels[0]. + mbms_SessionList[i]->list.count); + } + } #endif - if (radioResourceConfigCommon!=NULL) { - AssertFatal(RC.mac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n"); - PHY_Config_t phycfg; - phycfg.Mod_id = Mod_idP; - phycfg.CC_id = CC_idP; - phycfg.cfg = &RC.mac[Mod_idP]->config[CC_idP]; - - if (RC.mac[Mod_idP]->if_inst->PHY_config_req) RC.mac[Mod_idP]->if_inst->PHY_config_req(&phycfg); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT); - - return(0); + if (radioResourceConfigCommon != NULL) { + AssertFatal(RC.mac[Mod_idP]->if_inst->PHY_config_req != NULL, + "if_inst->phy_config_request is null\n"); + PHY_Config_t phycfg; + phycfg.Mod_id = Mod_idP; + phycfg.CC_id = CC_idP; + phycfg.cfg = &RC.mac[Mod_idP]->config[CC_idP]; + + if (RC.mac[Mod_idP]->if_inst->PHY_config_req) + RC.mac[Mod_idP]->if_inst->PHY_config_req(&phycfg); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT); + + return (0); } int -rrc_mac_config_req_ue( - module_id_t Mod_idP, - int CC_idP, - uint8_t eNB_index, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, - struct PhysicalConfigDedicated *physicalConfigDedicated, +rrc_mac_config_req_ue(module_id_t Mod_idP, + int CC_idP, + uint8_t eNB_index, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon, + struct PhysicalConfigDedicated + *physicalConfigDedicated, #if defined(Rel10) || defined(Rel14) - SCellToAddMod_r10_t *sCellToAddMod_r10, - //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, + SCellToAddMod_r10_t * sCellToAddMod_r10, + //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif - MeasObjectToAddMod_t **measObj, - MAC_MainConfig_t *mac_MainConfig, - long logicalChannelIdentity, - LogicalChannelConfig_t *logicalChannelConfig, - MeasGapConfig_t *measGapConfig, - TDD_Config_t *tdd_Config, - MobilityControlInfo_t *mobilityControlInfo, - uint8_t *SIwindowsize, - uint16_t *SIperiod, - ARFCN_ValueEUTRA_t *ul_CarrierFreq, - long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList + MeasObjectToAddMod_t ** measObj, + MAC_MainConfig_t * mac_MainConfig, + long logicalChannelIdentity, + LogicalChannelConfig_t * logicalChannelConfig, + MeasGapConfig_t * measGapConfig, + TDD_Config_t * tdd_Config, + MobilityControlInfo_t * mobilityControlInfo, + uint8_t * SIwindowsize, + uint16_t * SIperiod, + ARFCN_ValueEUTRA_t * ul_CarrierFreq, + long *ul_Bandwidth, + AdditionalSpectrumEmission_t * + additionalSpectrumEmission, + struct MBSFN_SubframeConfigList + *mbsfn_SubframeConfigList #if defined(Rel10) || defined(Rel14) - ,uint8_t MBMS_Flag, - MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, - PMCH_InfoList_r9_t *pmch_InfoList + , uint8_t MBMS_Flag, + MBSFN_AreaInfoList_r9_t * mbsfn_AreaInfoList, + PMCH_InfoList_r9_t * pmch_InfoList #endif #ifdef CBA - ,uint8_t num_active_cba_groups, - uint16_t cba_rnti + , uint8_t num_active_cba_groups, uint16_t cba_rnti #endif - ) + ) { - int i; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); - - LOG_I(MAC,"[CONFIG][UE %d] Configuring MAC/PHY from eNB %d\n",Mod_idP,eNB_index); - - if (tdd_Config != NULL) { - UE_mac_inst[Mod_idP].tdd_Config = tdd_Config; - } - - - if (tdd_Config && SIwindowsize && SIperiod) { - phy_config_sib1_ue(Mod_idP,0,eNB_index,tdd_Config,*SIwindowsize,*SIperiod); - } - - if (radioResourceConfigCommon!=NULL) { - UE_mac_inst[Mod_idP].radioResourceConfigCommon = radioResourceConfigCommon; - phy_config_sib2_ue(Mod_idP,0,eNB_index,radioResourceConfigCommon,ul_CarrierFreq,ul_Bandwidth,additionalSpectrumEmission,mbsfn_SubframeConfigList); - } - - // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup - if (logicalChannelConfig!= NULL) { - LOG_I(MAC,"[CONFIG][UE %d] Applying RRC logicalChannelConfig from eNB%d\n",Mod_idP,eNB_index); - UE_mac_inst[Mod_idP].logicalChannelConfig[logicalChannelIdentity]=logicalChannelConfig; - UE_mac_inst[Mod_idP].scheduling_info.Bj[logicalChannelIdentity]=0; // initilize the bucket for this lcid - - AssertFatal(logicalChannelConfig->ul_SpecificParameters!=NULL, - "[UE %d] LCID %ld NULL ul_SpecificParameters\n", - Mod_idP,logicalChannelIdentity); - UE_mac_inst[Mod_idP].scheduling_info.bucket_size[logicalChannelIdentity]=logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate * - logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration; // set the max bucket size - if (logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup != NULL) { - UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity]=*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; - LOG_D(MAC,"[CONFIG][UE %d] LCID %ld is attached to the LCGID %ld\n",Mod_idP,logicalChannelIdentity,*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup); + int i; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); + + LOG_I(MAC, "[CONFIG][UE %d] Configuring MAC/PHY from eNB %d\n", + Mod_idP, eNB_index); + + if (tdd_Config != NULL) { + UE_mac_inst[Mod_idP].tdd_Config = tdd_Config; } - else { - UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity] = MAX_NUM_LCGID; + + + if (tdd_Config && SIwindowsize && SIperiod) { + phy_config_sib1_ue(Mod_idP, 0, eNB_index, tdd_Config, + *SIwindowsize, *SIperiod); } - UE_mac_inst[Mod_idP].scheduling_info.LCID_buffer_remain[logicalChannelIdentity] = 0; - } - - if (mac_MainConfig != NULL) { - LOG_I(MAC,"[CONFIG][UE%d] Applying RRC macMainConfig from eNB%d\n",Mod_idP,eNB_index); - UE_mac_inst[Mod_idP].macConfig=mac_MainConfig; - UE_mac_inst[Mod_idP].measGapConfig=measGapConfig; - - if (mac_MainConfig->ul_SCH_Config) { - - if (mac_MainConfig->ul_SCH_Config->periodicBSR_Timer) { - UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = (uint16_t) *mac_MainConfig->ul_SCH_Config->periodicBSR_Timer; - } else { - UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = + + if (radioResourceConfigCommon != NULL) { + UE_mac_inst[Mod_idP].radioResourceConfigCommon = + radioResourceConfigCommon; + phy_config_sib2_ue(Mod_idP, 0, eNB_index, + radioResourceConfigCommon, ul_CarrierFreq, + ul_Bandwidth, additionalSpectrumEmission, + mbsfn_SubframeConfigList); + } + // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup + if (logicalChannelConfig != NULL) { + LOG_I(MAC, + "[CONFIG][UE %d] Applying RRC logicalChannelConfig from eNB%d\n", + Mod_idP, eNB_index); + UE_mac_inst[Mod_idP].logicalChannelConfig[logicalChannelIdentity] = + logicalChannelConfig; + UE_mac_inst[Mod_idP].scheduling_info.Bj[logicalChannelIdentity] = 0; // initilize the bucket for this lcid + + AssertFatal(logicalChannelConfig->ul_SpecificParameters != NULL, + "[UE %d] LCID %ld NULL ul_SpecificParameters\n", + Mod_idP, logicalChannelIdentity); + UE_mac_inst[Mod_idP].scheduling_info.bucket_size[logicalChannelIdentity] = logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate * logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration; // set the max bucket size + if (logicalChannelConfig->ul_SpecificParameters-> + logicalChannelGroup != NULL) { + UE_mac_inst[Mod_idP].scheduling_info. + LCGID[logicalChannelIdentity] = + *logicalChannelConfig->ul_SpecificParameters-> + logicalChannelGroup; + LOG_D(MAC, + "[CONFIG][UE %d] LCID %ld is attached to the LCGID %ld\n", + Mod_idP, logicalChannelIdentity, + *logicalChannelConfig-> + ul_SpecificParameters->logicalChannelGroup); + } else { + UE_mac_inst[Mod_idP].scheduling_info. + LCGID[logicalChannelIdentity] = MAX_NUM_LCGID; + } + UE_mac_inst[Mod_idP]. + scheduling_info.LCID_buffer_remain[logicalChannelIdentity] = 0; + } + + if (mac_MainConfig != NULL) { + LOG_I(MAC, + "[CONFIG][UE%d] Applying RRC macMainConfig from eNB%d\n", + Mod_idP, eNB_index); + UE_mac_inst[Mod_idP].macConfig = mac_MainConfig; + UE_mac_inst[Mod_idP].measGapConfig = measGapConfig; + + if (mac_MainConfig->ul_SCH_Config) { + + if (mac_MainConfig->ul_SCH_Config->periodicBSR_Timer) { + UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = + (uint16_t) * + mac_MainConfig->ul_SCH_Config->periodicBSR_Timer; + } else { + UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = #ifndef Rel14 - (uint16_t) MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity + (uint16_t) + MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity #else - (uint16_t) PeriodicBSR_Timer_r12_infinity; + (uint16_t) PeriodicBSR_Timer_r12_infinity; #endif - ; - } - - if (mac_MainConfig->ul_SCH_Config->maxHARQ_Tx) { - UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx = (uint16_t) *mac_MainConfig->ul_SCH_Config->maxHARQ_Tx; - } else { - UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx = (uint16_t) MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; - } - phy_config_harq_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx); - - if (mac_MainConfig->ul_SCH_Config->retxBSR_Timer) { - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t) mac_MainConfig->ul_SCH_Config->retxBSR_Timer; - } else { + ; + } + + if (mac_MainConfig->ul_SCH_Config->maxHARQ_Tx) { + UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx = + (uint16_t) * mac_MainConfig->ul_SCH_Config->maxHARQ_Tx; + } else { + UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx = + (uint16_t) + MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; + } + phy_config_harq_ue(Mod_idP, 0, eNB_index, + UE_mac_inst[Mod_idP]. + scheduling_info.maxHARQ_Tx); + + if (mac_MainConfig->ul_SCH_Config->retxBSR_Timer) { + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = + (uint16_t) mac_MainConfig->ul_SCH_Config-> + retxBSR_Timer; + } else { #ifndef Rel14 - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t)MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560; + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = + (uint16_t) + MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560; #else - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t)RetxBSR_Timer_r12_sf2560; + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = + (uint16_t) RetxBSR_Timer_r12_sf2560; #endif - } - } - - + } + } #if defined(Rel10) || defined(Rel14) - - if (mac_MainConfig->ext1 && mac_MainConfig->ext1->sr_ProhibitTimer_r9) { - UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = (uint16_t) *mac_MainConfig->ext1->sr_ProhibitTimer_r9; - } else { - UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = 0; - } - - if (mac_MainConfig->ext2 && mac_MainConfig->ext2->mac_MainConfig_v1020) { - if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10) { - UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10; - } else { - UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0; - } - if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10) { - UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10; - } else { - UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0; - } - } else { - UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0; - UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0; - } + + if (mac_MainConfig->ext1 + && mac_MainConfig->ext1->sr_ProhibitTimer_r9) { + UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = + (uint16_t) * mac_MainConfig->ext1->sr_ProhibitTimer_r9; + } else { + UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = 0; + } + + if (mac_MainConfig->ext2 + && mac_MainConfig->ext2->mac_MainConfig_v1020) { + if (mac_MainConfig->ext2-> + mac_MainConfig_v1020->extendedBSR_Sizes_r10) { + UE_mac_inst[Mod_idP].scheduling_info. + extendedBSR_Sizes_r10 = + (uint16_t) * + mac_MainConfig->ext2-> + mac_MainConfig_v1020->extendedBSR_Sizes_r10; + } else { + UE_mac_inst[Mod_idP].scheduling_info. + extendedBSR_Sizes_r10 = (uint16_t) 0; + } + if (mac_MainConfig->ext2->mac_MainConfig_v1020-> + extendedPHR_r10) { + UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = + (uint16_t) * + mac_MainConfig->ext2->mac_MainConfig_v1020-> + extendedPHR_r10; + } else { + UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = + (uint16_t) 0; + } + } else { + UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = + (uint16_t) 0; + UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = + (uint16_t) 0; + } #endif - UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; - - UE_mac_inst[Mod_idP].BSR_reporting_active = BSR_TRIGGER_NONE; - - LOG_D(MAC,"[UE %d]: periodic BSR %d (SF), retx BSR %d (SF)\n", - Mod_idP, - UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF, - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF); - - UE_mac_inst[Mod_idP].scheduling_info.drx_config = mac_MainConfig->drx_Config; - UE_mac_inst[Mod_idP].scheduling_info.phr_config = mac_MainConfig->phr_Config; - - if (mac_MainConfig->phr_Config) { - UE_mac_inst[Mod_idP].PHR_state = mac_MainConfig->phr_Config->present; - UE_mac_inst[Mod_idP].PHR_reconfigured = 1; - UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer = mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer; - UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer = mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer; - UE_mac_inst[Mod_idP].scheduling_info.PathlossChange = mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange; - } else { - UE_mac_inst[Mod_idP].PHR_reconfigured = 0; - UE_mac_inst[Mod_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup; - UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; - UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; - UE_mac_inst[Mod_idP].scheduling_info.PathlossChange = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; + UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + + UE_mac_inst[Mod_idP].BSR_reporting_active = BSR_TRIGGER_NONE; + + LOG_D(MAC, "[UE %d]: periodic BSR %d (SF), retx BSR %d (SF)\n", + Mod_idP, + UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF, + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF); + + UE_mac_inst[Mod_idP].scheduling_info.drx_config = + mac_MainConfig->drx_Config; + UE_mac_inst[Mod_idP].scheduling_info.phr_config = + mac_MainConfig->phr_Config; + + if (mac_MainConfig->phr_Config) { + UE_mac_inst[Mod_idP].PHR_state = + mac_MainConfig->phr_Config->present; + UE_mac_inst[Mod_idP].PHR_reconfigured = 1; + UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer = + mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer; + UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer = + mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer; + UE_mac_inst[Mod_idP].scheduling_info.PathlossChange = + mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange; + } else { + UE_mac_inst[Mod_idP].PHR_reconfigured = 0; + UE_mac_inst[Mod_idP].PHR_state = + MAC_MainConfig__phr_Config_PR_setup; + UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer = + MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; + UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer = + MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; + UE_mac_inst[Mod_idP].scheduling_info.PathlossChange = + MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; + } + + UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF = + get_sf_perioidicPHR_Timer(UE_mac_inst[Mod_idP]. + scheduling_info.periodicPHR_Timer); + UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF = + get_sf_prohibitPHR_Timer(UE_mac_inst[Mod_idP]. + scheduling_info.prohibitPHR_Timer); + UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db = + get_db_dl_PathlossChange(UE_mac_inst[Mod_idP]. + scheduling_info.PathlossChange); + UE_mac_inst[Mod_idP].PHR_reporting_active = 0; + LOG_D(MAC, + "[UE %d] config PHR (%d): periodic %d (SF) prohibit %d (SF) pathlosschange %d (db) \n", + Mod_idP, + (mac_MainConfig->phr_Config) ? mac_MainConfig-> + phr_Config->present : -1, + UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF, + UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF, + UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db); } - - UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF = get_sf_perioidicPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer); - UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF = get_sf_prohibitPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer); - UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db = get_db_dl_PathlossChange(UE_mac_inst[Mod_idP].scheduling_info.PathlossChange); - UE_mac_inst[Mod_idP].PHR_reporting_active = 0; - LOG_D(MAC,"[UE %d] config PHR (%d): periodic %d (SF) prohibit %d (SF) pathlosschange %d (db) \n", - Mod_idP, - (mac_MainConfig->phr_Config)?mac_MainConfig->phr_Config->present:-1, - UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF, - UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF, - UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db); - } - - - if (physicalConfigDedicated != NULL) { - phy_config_dedicated_ue(Mod_idP,0,eNB_index,physicalConfigDedicated); - UE_mac_inst[Mod_idP].physicalConfigDedicated=physicalConfigDedicated; // for SR proc - } -#if defined(Rel10) || defined(Rel14) - if (sCellToAddMod_r10 != NULL) { + if (physicalConfigDedicated != NULL) { + phy_config_dedicated_ue(Mod_idP, 0, eNB_index, + physicalConfigDedicated); + UE_mac_inst[Mod_idP].physicalConfigDedicated = physicalConfigDedicated; // for SR proc + } +#if defined(Rel10) || defined(Rel14) + if (sCellToAddMod_r10 != NULL) { - phy_config_dedicated_scell_ue(Mod_idP,eNB_index,sCellToAddMod_r10,1); - UE_mac_inst[Mod_idP].physicalConfigDedicatedSCell_r10 = sCellToAddMod_r10->radioResourceConfigDedicatedSCell_r10->physicalConfigDedicatedSCell_r10; // using SCell index 0 - } - + phy_config_dedicated_scell_ue(Mod_idP, eNB_index, + sCellToAddMod_r10, 1); + UE_mac_inst[Mod_idP].physicalConfigDedicatedSCell_r10 = sCellToAddMod_r10->radioResourceConfigDedicatedSCell_r10->physicalConfigDedicatedSCell_r10; // using SCell index 0 + } #endif - if (measObj!= NULL) { - if (measObj[0]!= NULL) { - UE_mac_inst[Mod_idP].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count; - LOG_I(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_idP].n_adj_cells); - - for (i=0; i<UE_mac_inst[Mod_idP].n_adj_cells; i++) { - UE_mac_inst[Mod_idP].adj_cell_id[i] = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.array[i]->physCellId; - LOG_I(MAC,"Cell %d : Nid_cell %d\n",i,UE_mac_inst[Mod_idP].adj_cell_id[i]); - } - - phy_config_meas_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].n_adj_cells,UE_mac_inst[Mod_idP].adj_cell_id); - } - } - - - if(mobilityControlInfo != NULL) { - - LOG_D(MAC,"[UE%d] MAC Reset procedure triggered by RRC eNB %d \n",Mod_idP,eNB_index); - ue_mac_reset(Mod_idP,eNB_index); - - if(mobilityControlInfo->radioResourceConfigCommon.rach_ConfigCommon) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->rach_ConfigCommon, - (void *)mobilityControlInfo->radioResourceConfigCommon.rach_ConfigCommon, - sizeof(RACH_ConfigCommon_t)); - } - - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->prach_Config.prach_ConfigInfo, - (void *)mobilityControlInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo, - sizeof(PRACH_ConfigInfo_t)); - UE_mac_inst[Mod_idP].radioResourceConfigCommon->prach_Config.rootSequenceIndex = mobilityControlInfo->radioResourceConfigCommon.prach_Config.rootSequenceIndex; - - if(mobilityControlInfo->radioResourceConfigCommon.pdsch_ConfigCommon) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->pdsch_ConfigCommon, - (void *)mobilityControlInfo->radioResourceConfigCommon.pdsch_ConfigCommon, - sizeof(PDSCH_ConfigCommon_t)); - } - - // not a pointer: mobilityControlInfo->radioResourceConfigCommon.pusch_ConfigCommon - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->pusch_ConfigCommon, - (void *)&mobilityControlInfo->radioResourceConfigCommon.pusch_ConfigCommon, - sizeof(PUSCH_ConfigCommon_t)); - - if(mobilityControlInfo->radioResourceConfigCommon.phich_Config) { - /* memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->phich_Config, - (void *)mobilityControlInfo->radioResourceConfigCommon.phich_Config, - sizeof(PHICH_Config_t)); */ - } - - if(mobilityControlInfo->radioResourceConfigCommon.pucch_ConfigCommon) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->pucch_ConfigCommon, - (void *)mobilityControlInfo->radioResourceConfigCommon.pucch_ConfigCommon, - sizeof(PUCCH_ConfigCommon_t)); - } - - if(mobilityControlInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->soundingRS_UL_ConfigCommon, - (void *)mobilityControlInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon, - sizeof(SoundingRS_UL_ConfigCommon_t)); - } - - if(mobilityControlInfo->radioResourceConfigCommon.uplinkPowerControlCommon) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->uplinkPowerControlCommon, - (void *)mobilityControlInfo->radioResourceConfigCommon.uplinkPowerControlCommon, - sizeof(UplinkPowerControlCommon_t)); - } - - //configure antennaInfoCommon somewhere here.. - if(mobilityControlInfo->radioResourceConfigCommon.p_Max) { - //to be configured - } - - if(mobilityControlInfo->radioResourceConfigCommon.tdd_Config) { - UE_mac_inst[Mod_idP].tdd_Config = mobilityControlInfo->radioResourceConfigCommon.tdd_Config; - } - - if(mobilityControlInfo->radioResourceConfigCommon.ul_CyclicPrefixLength) { - memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->ul_CyclicPrefixLength, - (void *)mobilityControlInfo->radioResourceConfigCommon.ul_CyclicPrefixLength, - sizeof(UL_CyclicPrefixLength_t)); - } - - // store the previous rnti in case of failure, and set thenew rnti - UE_mac_inst[Mod_idP].crnti_before_ho = UE_mac_inst[Mod_idP].crnti; - UE_mac_inst[Mod_idP].crnti = ((mobilityControlInfo->newUE_Identity.buf[0])|(mobilityControlInfo->newUE_Identity.buf[1]<<8)); - LOG_I(MAC,"[UE %d] Received new identity %x from %d\n", Mod_idP, UE_mac_inst[Mod_idP].crnti, eNB_index); - UE_mac_inst[Mod_idP].rach_ConfigDedicated = malloc(sizeof(*mobilityControlInfo->rach_ConfigDedicated)); - - if (mobilityControlInfo->rach_ConfigDedicated) { - memcpy((void*)UE_mac_inst[Mod_idP].rach_ConfigDedicated, - (void*)mobilityControlInfo->rach_ConfigDedicated, - sizeof(*mobilityControlInfo->rach_ConfigDedicated)); + if (measObj != NULL) { + if (measObj[0] != NULL) { + UE_mac_inst[Mod_idP].n_adj_cells = + measObj[0]->measObject.choice. + measObjectEUTRA.cellsToAddModList->list.count; + LOG_I(MAC, "Number of adjacent cells %d\n", + UE_mac_inst[Mod_idP].n_adj_cells); + + for (i = 0; i < UE_mac_inst[Mod_idP].n_adj_cells; i++) { + UE_mac_inst[Mod_idP].adj_cell_id[i] = + measObj[0]->measObject.choice. + measObjectEUTRA.cellsToAddModList->list.array[i]-> + physCellId; + LOG_I(MAC, "Cell %d : Nid_cell %d\n", i, + UE_mac_inst[Mod_idP].adj_cell_id[i]); + } + + phy_config_meas_ue(Mod_idP, 0, eNB_index, + UE_mac_inst[Mod_idP].n_adj_cells, + UE_mac_inst[Mod_idP].adj_cell_id); + } } - - phy_config_afterHO_ue(Mod_idP,0,eNB_index,mobilityControlInfo,0); - } - - - if (mbsfn_SubframeConfigList != NULL) { - LOG_I(MAC,"[UE %d][CONFIG] Received %d subframe allocation pattern for MBSFN\n", Mod_idP, mbsfn_SubframeConfigList->list.count); - UE_mac_inst[Mod_idP].num_sf_allocation_pattern= mbsfn_SubframeConfigList->list.count; - - for (i=0; i<mbsfn_SubframeConfigList->list.count; i++) { - LOG_I(MAC, "[UE %d] Configuring MBSFN_SubframeConfig %d from received SIB2 \n", Mod_idP, i); - UE_mac_inst[Mod_idP].mbsfn_SubframeConfig[i] = mbsfn_SubframeConfigList->list.array[i]; - // LOG_I("[UE %d] MBSFN_SubframeConfig[%d] pattern is %ld\n", Mod_idP, - // UE_mac_inst[Mod_idP].mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0]); + + + if (mobilityControlInfo != NULL) { + + LOG_D(MAC, "[UE%d] MAC Reset procedure triggered by RRC eNB %d \n", + Mod_idP, eNB_index); + ue_mac_reset(Mod_idP, eNB_index); + + if (mobilityControlInfo->radioResourceConfigCommon. + rach_ConfigCommon) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + rach_ConfigCommon, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.rach_ConfigCommon, + sizeof(RACH_ConfigCommon_t)); + } + + memcpy((void *) &UE_mac_inst[Mod_idP]. + radioResourceConfigCommon->prach_Config.prach_ConfigInfo, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.prach_Config.prach_ConfigInfo, + sizeof(PRACH_ConfigInfo_t)); + UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + prach_Config.rootSequenceIndex = + mobilityControlInfo->radioResourceConfigCommon. + prach_Config.rootSequenceIndex; + + if (mobilityControlInfo->radioResourceConfigCommon. + pdsch_ConfigCommon) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + pdsch_ConfigCommon, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.pdsch_ConfigCommon, + sizeof(PDSCH_ConfigCommon_t)); + } + // not a pointer: mobilityControlInfo->radioResourceConfigCommon.pusch_ConfigCommon + memcpy((void *) &UE_mac_inst[Mod_idP]. + radioResourceConfigCommon->pusch_ConfigCommon, + (void *) &mobilityControlInfo-> + radioResourceConfigCommon.pusch_ConfigCommon, + sizeof(PUSCH_ConfigCommon_t)); + + if (mobilityControlInfo->radioResourceConfigCommon.phich_Config) { + /* memcpy((void *)&UE_mac_inst[Mod_idP].radioResourceConfigCommon->phich_Config, + (void *)mobilityControlInfo->radioResourceConfigCommon.phich_Config, + sizeof(PHICH_Config_t)); */ + } + + if (mobilityControlInfo->radioResourceConfigCommon. + pucch_ConfigCommon) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + pucch_ConfigCommon, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.pucch_ConfigCommon, + sizeof(PUCCH_ConfigCommon_t)); + } + + if (mobilityControlInfo-> + radioResourceConfigCommon.soundingRS_UL_ConfigCommon) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + soundingRS_UL_ConfigCommon, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.soundingRS_UL_ConfigCommon, + sizeof(SoundingRS_UL_ConfigCommon_t)); + } + + if (mobilityControlInfo-> + radioResourceConfigCommon.uplinkPowerControlCommon) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + uplinkPowerControlCommon, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.uplinkPowerControlCommon, + sizeof(UplinkPowerControlCommon_t)); + } + //configure antennaInfoCommon somewhere here.. + if (mobilityControlInfo->radioResourceConfigCommon.p_Max) { + //to be configured + } + + if (mobilityControlInfo->radioResourceConfigCommon.tdd_Config) { + UE_mac_inst[Mod_idP].tdd_Config = + mobilityControlInfo->radioResourceConfigCommon.tdd_Config; + } + + if (mobilityControlInfo-> + radioResourceConfigCommon.ul_CyclicPrefixLength) { + memcpy((void *) + &UE_mac_inst[Mod_idP].radioResourceConfigCommon-> + ul_CyclicPrefixLength, + (void *) mobilityControlInfo-> + radioResourceConfigCommon.ul_CyclicPrefixLength, + sizeof(UL_CyclicPrefixLength_t)); + } + // store the previous rnti in case of failure, and set thenew rnti + UE_mac_inst[Mod_idP].crnti_before_ho = UE_mac_inst[Mod_idP].crnti; + UE_mac_inst[Mod_idP].crnti = + ((mobilityControlInfo-> + newUE_Identity.buf[0]) | (mobilityControlInfo-> + newUE_Identity.buf[1] << 8)); + LOG_I(MAC, "[UE %d] Received new identity %x from %d\n", Mod_idP, + UE_mac_inst[Mod_idP].crnti, eNB_index); + UE_mac_inst[Mod_idP].rach_ConfigDedicated = + malloc(sizeof(*mobilityControlInfo->rach_ConfigDedicated)); + + if (mobilityControlInfo->rach_ConfigDedicated) { + memcpy((void *) UE_mac_inst[Mod_idP].rach_ConfigDedicated, + (void *) mobilityControlInfo->rach_ConfigDedicated, + sizeof(*mobilityControlInfo->rach_ConfigDedicated)); + } + + phy_config_afterHO_ue(Mod_idP, 0, eNB_index, mobilityControlInfo, + 0); } - } - -#if defined(Rel10) || defined(Rel14) - if (mbsfn_AreaInfoList != NULL) { - LOG_I(MAC,"[UE %d][CONFIG] Received %d MBSFN Area Info\n", Mod_idP, mbsfn_AreaInfoList->list.count); - UE_mac_inst[Mod_idP].num_active_mbsfn_area = mbsfn_AreaInfoList->list.count; - - for (i =0; i< mbsfn_AreaInfoList->list.count; i++) { - UE_mac_inst[Mod_idP].mbsfn_AreaInfo[i] = mbsfn_AreaInfoList->list.array[i]; - LOG_I(MAC,"[UE %d] MBSFN_AreaInfo[%d]: MCCH Repetition Period = %ld\n",Mod_idP, i, - UE_mac_inst[Mod_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9); - phy_config_sib13_ue(Mod_idP,0,eNB_index,i,UE_mac_inst[Mod_idP].mbsfn_AreaInfo[i]->mbsfn_AreaId_r9); + if (mbsfn_SubframeConfigList != NULL) { + LOG_I(MAC, + "[UE %d][CONFIG] Received %d subframe allocation pattern for MBSFN\n", + Mod_idP, mbsfn_SubframeConfigList->list.count); + UE_mac_inst[Mod_idP].num_sf_allocation_pattern = + mbsfn_SubframeConfigList->list.count; + + for (i = 0; i < mbsfn_SubframeConfigList->list.count; i++) { + LOG_I(MAC, + "[UE %d] Configuring MBSFN_SubframeConfig %d from received SIB2 \n", + Mod_idP, i); + UE_mac_inst[Mod_idP].mbsfn_SubframeConfig[i] = + mbsfn_SubframeConfigList->list.array[i]; + // LOG_I("[UE %d] MBSFN_SubframeConfig[%d] pattern is %ld\n", Mod_idP, + // UE_mac_inst[Mod_idP].mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0]); + } } - } - - if (pmch_InfoList != NULL) { - - // LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9)); - - LOG_I(MAC, "[UE %d] Configuring PMCH_config from MCCH MESSAGE \n",Mod_idP); - - for (i =0; i< pmch_InfoList->list.count; i++) { - UE_mac_inst[Mod_idP].pmch_Config[i] = &pmch_InfoList->list.array[i]->pmch_Config_r9; - LOG_I(MAC, "[UE %d] PMCH[%d]: MCH_Scheduling_Period = %ld\n", Mod_idP, i, - UE_mac_inst[Mod_idP].pmch_Config[i]->mch_SchedulingPeriod_r9); +#if defined(Rel10) || defined(Rel14) + + if (mbsfn_AreaInfoList != NULL) { + LOG_I(MAC, "[UE %d][CONFIG] Received %d MBSFN Area Info\n", + Mod_idP, mbsfn_AreaInfoList->list.count); + UE_mac_inst[Mod_idP].num_active_mbsfn_area = + mbsfn_AreaInfoList->list.count; + + for (i = 0; i < mbsfn_AreaInfoList->list.count; i++) { + UE_mac_inst[Mod_idP].mbsfn_AreaInfo[i] = + mbsfn_AreaInfoList->list.array[i]; + LOG_I(MAC, + "[UE %d] MBSFN_AreaInfo[%d]: MCCH Repetition Period = %ld\n", + Mod_idP, i, + UE_mac_inst[Mod_idP].mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_RepetitionPeriod_r9); + phy_config_sib13_ue(Mod_idP, 0, eNB_index, i, + UE_mac_inst[Mod_idP]. + mbsfn_AreaInfo[i]->mbsfn_AreaId_r9); + } } - - UE_mac_inst[Mod_idP].mcch_status = 1; - } + if (pmch_InfoList != NULL) { + + // LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9)); + LOG_I(MAC, "[UE %d] Configuring PMCH_config from MCCH MESSAGE \n", + Mod_idP); + + for (i = 0; i < pmch_InfoList->list.count; i++) { + UE_mac_inst[Mod_idP].pmch_Config[i] = + &pmch_InfoList->list.array[i]->pmch_Config_r9; + LOG_I(MAC, "[UE %d] PMCH[%d]: MCH_Scheduling_Period = %ld\n", + Mod_idP, i, + UE_mac_inst[Mod_idP]. + pmch_Config[i]->mch_SchedulingPeriod_r9); + } + + UE_mac_inst[Mod_idP].mcch_status = 1; + } #endif #ifdef CBA - if (cba_rnti) { - UE_mac_inst[Mod_idP].cba_rnti[num_active_cba_groups-1] = cba_rnti; - LOG_D(MAC,"[UE %d] configure CBA group %d RNTI %x for eNB %d (total active cba group %d)\n", - Mod_idP,Mod_idP%num_active_cba_groups, cba_rnti,eNB_index,num_active_cba_groups); - phy_config_cba_rnti(Mod_idP,CC_idP,eNB_flagP,eNB_index,cba_rnti,num_active_cba_groups-1, num_active_cba_groups); - } + if (cba_rnti) { + UE_mac_inst[Mod_idP].cba_rnti[num_active_cba_groups - 1] = + cba_rnti; + LOG_D(MAC, + "[UE %d] configure CBA group %d RNTI %x for eNB %d (total active cba group %d)\n", + Mod_idP, Mod_idP % num_active_cba_groups, cba_rnti, + eNB_index, num_active_cba_groups); + phy_config_cba_rnti(Mod_idP, CC_idP, eNB_flagP, eNB_index, + cba_rnti, num_active_cba_groups - 1, + num_active_cba_groups); + } #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT); - return(0); + return (0); } - diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index 0c9e1498208c8d63896dc01366e18db5b6134689..43d8167fe604315290e416dbd8190fbfcffae392 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -90,12 +90,12 @@ #if defined(Rel10) || defined(Rel14) // Mask for identifying subframe for MBMS -#define MBSFN_TDD_SF3 0x80// for TDD +#define MBSFN_TDD_SF3 0x80 // for TDD #define MBSFN_TDD_SF4 0x40 #define MBSFN_TDD_SF7 0x20 #define MBSFN_TDD_SF8 0x10 #define MBSFN_TDD_SF9 0x08 -#define MBSFN_FDD_SF1 0x80// for FDD +#define MBSFN_FDD_SF1 0x80 // for FDD #define MBSFN_FDD_SF2 0x40 #define MBSFN_FDD_SF3 0x20 #define MBSFN_FDD_SF6 0x10 @@ -111,7 +111,7 @@ #ifdef USER_MODE #define printk printf -#endif //USER_MODE +#endif //USER_MODE /*!\brief Maximum number of logical channl group IDs */ #define MAX_NUM_LCGID 4 @@ -136,17 +136,17 @@ /*!\brief size of buffer status report table */ #define BSR_TABLE_SIZE 64 /*!\brief The power headroom reporting range is from -23 ...+40 dB and beyond, with step 1 */ -#define PHR_MAPPING_OFFSET 23 // if ( x>= -23 ) val = floor (x + 23) +#define PHR_MAPPING_OFFSET 23 // if ( x>= -23 ) val = floor (x + 23) /*!\brief maximum number of resource block groups */ -#define N_RBG_MAX 25 // for 20MHz channel BW +#define N_RBG_MAX 25 // for 20MHz channel BW /*!\brief minimum value for channel quality indicator */ #define MIN_CQI_VALUE 0 /*!\brief maximum value for channel quality indicator */ #define MAX_CQI_VALUE 15 /*!\briefmaximum number of supported bandwidth (1.4, 5, 10, 20 MHz) */ -#define MAX_SUPPORTED_BW 4 +#define MAX_SUPPORTED_BW 4 /*!\brief CQI values range from 1 to 15 (4 bits) */ -#define CQI_VALUE_RANGE 16 +#define CQI_VALUE_RANGE 16 /*!\brief value for indicating BSR Timer is not running */ #define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) @@ -161,30 +161,30 @@ #define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE) /*!\brief maximum number of slices / groups */ -#define MAX_NUM_SLICES 4 +#define MAX_NUM_SLICES 4 /* * eNB part - */ + */ /* * UE/ENB common part - */ + */ /*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) */ typedef struct { - uint8_t RAPID:6; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_RAPID; + uint8_t RAPID:6; + uint8_t T:1; + uint8_t E:1; +} __attribute__ ((__packed__)) RA_HEADER_RAPID; /*!\brief MAC header of Random Access Response for backoff indicator (BI)*/ typedef struct { - uint8_t BI:4; - uint8_t R:2; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_BI; + uint8_t BI:4; + uint8_t R:2; + uint8_t T:1; + uint8_t E:1; +} __attribute__ ((__packed__)) RA_HEADER_BI; /* typedef struct { uint64_t padding:16; @@ -216,124 +216,124 @@ typedef struct { */ /*!\brief MAC subheader short with 7bit Length field */ typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L:7; // octet 2 LSB - uint8_t F:1; // octet 2 MSB -} __attribute__((__packed__))SCH_SUBHEADER_SHORT; + uint8_t LCID:5; // octet 1 LSB + uint8_t E:1; + uint8_t R:2; // octet 1 MSB + uint8_t L:7; // octet 2 LSB + uint8_t F:1; // octet 2 MSB +} __attribute__ ((__packed__)) SCH_SUBHEADER_SHORT; /*!\brief MAC subheader long with 15bit Length field */ typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L_MSB:7; - uint8_t F:1; // octet 2 MSB - uint8_t L_LSB:8; - uint8_t padding; -} __attribute__((__packed__))SCH_SUBHEADER_LONG; + uint8_t LCID:5; // octet 1 LSB + uint8_t E:1; + uint8_t R:2; // octet 1 MSB + uint8_t L_MSB:7; + uint8_t F:1; // octet 2 MSB + uint8_t L_LSB:8; + uint8_t padding; +} __attribute__ ((__packed__)) SCH_SUBHEADER_LONG; /*!\brief MAC subheader short without length field */ typedef struct { - uint8_t LCID:5; - uint8_t E:1; - uint8_t R:2; -} __attribute__((__packed__))SCH_SUBHEADER_FIXED; + uint8_t LCID:5; + uint8_t E:1; + uint8_t R:2; +} __attribute__ ((__packed__)) SCH_SUBHEADER_FIXED; /*!\brief mac control element: short buffer status report for a specific logical channel group ID*/ typedef struct { - uint8_t Buffer_size:6; // octet 1 LSB - uint8_t LCGID:2; // octet 1 MSB -} __attribute__((__packed__))BSR_SHORT; + uint8_t Buffer_size:6; // octet 1 LSB + uint8_t LCGID:2; // octet 1 MSB +} __attribute__ ((__packed__)) BSR_SHORT; typedef BSR_SHORT BSR_TRUNCATED; /*!\brief mac control element: long buffer status report for all logical channel group ID*/ typedef struct { - uint8_t Buffer_size3:6; - uint8_t Buffer_size2:6; - uint8_t Buffer_size1:6; - uint8_t Buffer_size0:6; -} __attribute__((__packed__))BSR_LONG; + uint8_t Buffer_size3:6; + uint8_t Buffer_size2:6; + uint8_t Buffer_size1:6; + uint8_t Buffer_size0:6; +} __attribute__ ((__packed__)) BSR_LONG; #define BSR_LONG_SIZE (sizeof(BSR_LONG)) /*!\brief mac control element: timing advance */ typedef struct { - uint8_t TA:6; - uint8_t R:2; -} __attribute__((__packed__))TIMING_ADVANCE_CMD; + uint8_t TA:6; + uint8_t R:2; +} __attribute__ ((__packed__)) TIMING_ADVANCE_CMD; /*!\brief mac control element: power headroom report */ typedef struct { - uint8_t PH:6; - uint8_t R:2; -} __attribute__((__packed__))POWER_HEADROOM_CMD; + uint8_t PH:6; + uint8_t R:2; +} __attribute__ ((__packed__)) POWER_HEADROOM_CMD; /*! \brief MIB payload */ typedef struct { - uint8_t payload[3] ; -} __attribute__((__packed__))MIB_PDU; + uint8_t payload[3]; +} __attribute__ ((__packed__)) MIB_PDU; /*! \brief CCCH payload */ typedef struct { - uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))CCCH_PDU; + uint8_t payload[CCCH_PAYLOAD_SIZE_MAX]; +} __attribute__ ((__packed__)) CCCH_PDU; /*! \brief BCCH payload */ typedef struct { - uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))BCCH_PDU; + uint8_t payload[BCCH_PAYLOAD_SIZE_MAX]; +} __attribute__ ((__packed__)) BCCH_PDU; /*! \brief RAR payload */ typedef struct { - uint8_t payload[RAR_PAYLOAD_SIZE_MAX]; + uint8_t payload[RAR_PAYLOAD_SIZE_MAX]; } __attribute__ ((__packed__)) RAR_PDU; /*! \brief BCCH payload */ typedef struct { - uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))PCCH_PDU; + uint8_t payload[PCCH_PAYLOAD_SIZE_MAX]; +} __attribute__ ((__packed__)) PCCH_PDU; #if defined(Rel10) || defined(Rel14) /*! \brief MCCH payload */ typedef struct { - uint8_t payload[MCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))MCCH_PDU; + uint8_t payload[MCCH_PAYLOAD_SIZE_MAX]; +} __attribute__ ((__packed__)) MCCH_PDU; /*!< \brief MAC control element for activation and deactivation of component carriers */ typedef struct { - uint8_t C7:1;/*!< \brief Component carrier 7 */ - uint8_t C6:1;/*!< \brief Component carrier 6 */ - uint8_t C5:1;/*!< \brief Component carrier 5 */ - uint8_t C4:1;/*!< \brief Component carrier 4 */ - uint8_t C3:1;/*!< \brief Component carrier 3 */ - uint8_t C2:1;/*!< \brief Component carrier 2 */ - uint8_t C1:1;/*!< \brief Component carrier 1 */ - uint8_t R:1;/*!< \brief Reserved */ -} __attribute__((__packed__))CC_ELEMENT; + uint8_t C7:1; /*!< \brief Component carrier 7 */ + uint8_t C6:1; /*!< \brief Component carrier 6 */ + uint8_t C5:1; /*!< \brief Component carrier 5 */ + uint8_t C4:1; /*!< \brief Component carrier 4 */ + uint8_t C3:1; /*!< \brief Component carrier 3 */ + uint8_t C2:1; /*!< \brief Component carrier 2 */ + uint8_t C1:1; /*!< \brief Component carrier 1 */ + uint8_t R:1; /*!< \brief Reserved */ +} __attribute__ ((__packed__)) CC_ELEMENT; /*! \brief MAC control element: MCH Scheduling Information */ typedef struct { - uint8_t stop_sf_MSB:3; // octet 1 LSB - uint8_t lcid:5; // octet 2 MSB - uint8_t stop_sf_LSB:8; -} __attribute__((__packed__))MSI_ELEMENT; + uint8_t stop_sf_MSB:3; // octet 1 LSB + uint8_t lcid:5; // octet 2 MSB + uint8_t stop_sf_LSB:8; +} __attribute__ ((__packed__)) MSI_ELEMENT; #endif -/*! \brief Values of CCCH LCID for DLSCH */ +/*! \brief Values of CCCH LCID for DLSCH */ #define CCCH_LCHANID 0 /*!\brief Values of BCCH logical channel (fake)*/ -#define BCCH 3 // SI +#define BCCH 3 // SI /*!\brief Values of PCCH logical channel (fake)*/ -#define PCCH 4 // Paging +#define PCCH 4 // Paging /*!\brief Values of PCCH logical channel (fake) */ -#define MIBCH 5 // MIB +#define MIBCH 5 // MIB /*!\brief Values of BCCH SIB1_BR logical channel (fake) */ -#define BCCH_SIB1_BR 6 // SIB1_BR +#define BCCH_SIB1_BR 6 // SIB1_BR /*!\brief Values of BCCH SIB_BR logical channel (fake) */ -#define BCCH_SI_BR 7 // SI-BR +#define BCCH_SI_BR 7 // SI-BR /*!\brief Value of CCCH / SRB0 logical channel */ -#define CCCH 0 // srb0 +#define CCCH 0 // srb0 /*!\brief DCCH / SRB1 logical channel */ -#define DCCH 1 // srb1 +#define DCCH 1 // srb1 /*!\brief DCCH1 / SRB2 logical channel */ -#define DCCH1 2 // srb2 +#define DCCH1 2 // srb2 /*!\brief DTCH DRB1 logical channel */ -#define DTCH 3 // LCID +#define DTCH 3 // LCID /*!\brief MCCH logical channel */ -#define MCCH 4 +#define MCCH 4 /*!\brief MTCH logical channel */ -#define MTCH 1 +#define MTCH 1 // DLSCH LCHAN ID /*!\brief LCID of UE contention resolution identity for DLSCH*/ #define UE_CONT_RES 28 @@ -368,972 +368,963 @@ typedef struct { /*!\brief LCID of long BSR for ULSCH */ #define LONG_BSR 30 /*!\bitmaps for BSR Triggers */ -#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */ -#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ -#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ -#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ +#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */ +#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ +#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ +#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ /*! \brief Downlink SCH PDU Structure */ typedef struct { - uint8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size[8]; + uint8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; + uint16_t Pdu_size[8]; } __attribute__ ((__packed__)) DLSCH_PDU; /*! \brief MCH PDU Structure */ typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size; - uint8_t mcs; - uint8_t sync_area; - uint8_t msi_active; - uint8_t mcch_active; - uint8_t mtch_active; + int8_t payload[SCH_PAYLOAD_SIZE_MAX]; + uint16_t Pdu_size; + uint8_t mcs; + uint8_t sync_area; + uint8_t msi_active; + uint8_t mcch_active; + uint8_t mtch_active; } __attribute__ ((__packed__)) MCH_PDU; /*! \brief Uplink SCH PDU Structure */ typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ - uint16_t Pdu_size; + int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ + uint16_t Pdu_size; } __attribute__ ((__packed__)) ULSCH_PDU; #include "PHY/impl_defs_top.h" +/*!\brief RA process state*/ +typedef enum { + IDLE = 0, + MSG2, + WAITMSG3, + MSG4, + WAITMSG4ACK +} RA_state; + /*!\brief UE ULSCH scheduling states*/ typedef enum { - S_UL_NONE =0, - S_UL_WAITING, - S_UL_SCHEDULED, - S_UL_BUFFERED, - S_UL_NUM_STATUS + S_UL_NONE = 0, + S_UL_WAITING, + S_UL_SCHEDULED, + S_UL_BUFFERED, + S_UL_NUM_STATUS } UE_ULSCH_STATUS; /*!\brief UE DLSCH scheduling states*/ typedef enum { - S_DL_NONE =0, - S_DL_WAITING, - S_DL_SCHEDULED, - S_DL_BUFFERED, - S_DL_NUM_STATUS + S_DL_NONE = 0, + S_DL_WAITING, + S_DL_SCHEDULED, + S_DL_BUFFERED, + S_DL_NUM_STATUS } UE_DLSCH_STATUS; /*!\brief scheduling policy for the contention-based access */ typedef enum { - CBA_ES=0, /// equal share of RB among groups w - CBA_ES_S, /// equal share of RB among groups with small allocation - CBA_PF, /// proportional fair (kind of) - CBA_PF_S, /// proportional fair (kind of) with small RB allocation - CBA_RS /// random allocation + CBA_ES = 0, /// equal share of RB among groups w + CBA_ES_S, /// equal share of RB among groups with small allocation + CBA_PF, /// proportional fair (kind of) + CBA_PF_S, /// proportional fair (kind of) with small RB allocation + CBA_RS /// random allocation } CBA_POLICY; /*! \brief temporary struct for ULSCH sched */ typedef struct { - rnti_t rnti; - uint16_t subframe; - uint16_t serving_num; - UE_ULSCH_STATUS status; + rnti_t rnti; + uint16_t subframe; + uint16_t serving_num; + UE_ULSCH_STATUS status; } eNB_ULSCH_INFO; /*! \brief temp struct for DLSCH sched */ typedef struct { - rnti_t rnti; - uint16_t weight; - uint16_t subframe; - uint16_t serving_num; - UE_DLSCH_STATUS status; + rnti_t rnti; + uint16_t weight; + uint16_t subframe; + uint16_t serving_num; + UE_DLSCH_STATUS status; } eNB_DLSCH_INFO; /*! \brief eNB overall statistics */ typedef struct { - /// num BCCH PDU per CC - uint32_t total_num_bcch_pdu; - /// BCCH buffer size - uint32_t bcch_buffer; - /// total BCCH buffer size - uint32_t total_bcch_buffer; - /// BCCH MCS - uint32_t bcch_mcs; - - /// num CCCH PDU per CC - uint32_t total_num_ccch_pdu; - /// BCCH buffer size - uint32_t ccch_buffer; - /// total BCCH buffer size - uint32_t total_ccch_buffer; - /// BCCH MCS - uint32_t ccch_mcs; + /// num BCCH PDU per CC + uint32_t total_num_bcch_pdu; + /// BCCH buffer size + uint32_t bcch_buffer; + /// total BCCH buffer size + uint32_t total_bcch_buffer; + /// BCCH MCS + uint32_t bcch_mcs; + + /// num CCCH PDU per CC + uint32_t total_num_ccch_pdu; + /// BCCH buffer size + uint32_t ccch_buffer; + /// total BCCH buffer size + uint32_t total_ccch_buffer; + /// BCCH MCS + uint32_t ccch_mcs; /// num active users - uint16_t num_dlactive_UEs; - /// available number of PRBs for a give SF - uint16_t available_prbs; - /// total number of PRB available for the user plane - uint32_t total_available_prbs; - /// aggregation - /// total avilable nccc : num control channel element - uint16_t available_ncces; - // only for a new transmission, should be extended for retransmission - // current dlsch bit rate for all transport channels - uint32_t dlsch_bitrate; - // - uint32_t dlsch_bytes_tx; - // - uint32_t dlsch_pdus_tx; - // - uint32_t total_dlsch_bitrate; - // - uint32_t total_dlsch_bytes_tx; - // - uint32_t total_dlsch_pdus_tx; - - // here for RX - // - uint32_t ulsch_bitrate; - // - uint32_t ulsch_bytes_rx; - // - uint64_t ulsch_pdus_rx; - - uint32_t total_ulsch_bitrate; - // - uint32_t total_ulsch_bytes_rx; - // - uint32_t total_ulsch_pdus_rx; - - - /// MAC agent-related stats - /// total number of scheduling decisions - int sched_decisions; - /// missed deadlines - int missed_deadlines; + uint16_t num_dlactive_UEs; + /// available number of PRBs for a give SF + uint16_t available_prbs; + /// total number of PRB available for the user plane + uint32_t total_available_prbs; + /// aggregation + /// total avilable nccc : num control channel element + uint16_t available_ncces; + // only for a new transmission, should be extended for retransmission + // current dlsch bit rate for all transport channels + uint32_t dlsch_bitrate; + // + uint32_t dlsch_bytes_tx; + // + uint32_t dlsch_pdus_tx; + // + uint32_t total_dlsch_bitrate; + // + uint32_t total_dlsch_bytes_tx; + // + uint32_t total_dlsch_pdus_tx; + + // here for RX + // + uint32_t ulsch_bitrate; + // + uint32_t ulsch_bytes_rx; + // + uint64_t ulsch_pdus_rx; + + uint32_t total_ulsch_bitrate; + // + uint32_t total_ulsch_bytes_rx; + // + uint32_t total_ulsch_pdus_rx; + + + /// MAC agent-related stats + /// total number of scheduling decisions + int sched_decisions; + /// missed deadlines + int missed_deadlines; } eNB_STATS; /*! \brief eNB statistics for the connected UEs*/ typedef struct { - /// CRNTI of UE - rnti_t crnti; ///user id (rnti) of connected UEs - // rrc status - uint8_t rrc_status; - /// harq pid - uint8_t harq_pid; - /// harq rounf - uint8_t harq_round; - /// total available number of PRBs for a new transmission - uint16_t rbs_used; - /// total available number of PRBs for a retransmission - uint16_t rbs_used_retx; - /// total nccc used for a new transmission: num control channel element - uint16_t ncce_used; - /// total avilable nccc for a retransmission: num control channel element - uint16_t ncce_used_retx; - - // mcs1 before the rate adaptaion - uint8_t dlsch_mcs1; - /// Target mcs2 after rate-adaptation - uint8_t dlsch_mcs2; - // current TBS with mcs2 - uint32_t TBS; - // total TBS with mcs2 - // uint32_t total_TBS; - // total rb used for a new transmission - uint32_t total_rbs_used; - // total rb used for retransmission - uint32_t total_rbs_used_retx; - - /// TX - /// Num pkt - uint32_t num_pdu_tx[NB_RB_MAX]; - /// num bytes - uint32_t num_bytes_tx[NB_RB_MAX]; - /// num retransmission / harq - uint32_t num_retransmission; - /// instantaneous tx throughput for each TTI - // uint32_t tti_throughput[NB_RB_MAX]; - - /// overall - // - uint32_t dlsch_bitrate; - //total - uint32_t total_dlsch_bitrate; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes; - // MAC multiplexed payload - uint64_t total_sdu_bytes; - // total MAC pdu bytes - uint64_t total_pdu_bytes; - - // total num pdu - uint32_t total_num_pdus; - // - // uint32_t avg_pdu_size; - - /// RX - - /// PUCCH1a/b power (dBm) - int32_t Po_PUCCH_dBm; - /// Indicator that Po_PUCCH has been updated by PHY - int32_t Po_PUCCH_update; - /// Uplink measured RSSI - int32_t UL_rssi; - /// preassigned mcs after rate adaptation - uint8_t ulsch_mcs1; - /// adjusted mcs - uint8_t ulsch_mcs2; - - /// estimated average pdu inter-departure time - uint32_t avg_pdu_idt; - /// estimated average pdu size - uint32_t avg_pdu_ps; - /// - uint32_t aggregated_pdu_size; - uint32_t aggregated_pdu_arrival; - - /// uplink transport block size - uint32_t ulsch_TBS; - - /// total rb used for a new uplink transmission - uint32_t num_retransmission_rx; - /// total rb used for a new uplink transmission - uint32_t rbs_used_rx; - /// total rb used for a new uplink retransmission - uint32_t rbs_used_retx_rx; - /// total rb used for a new uplink transmission - uint32_t total_rbs_used_rx; - /// normalized rx power - int32_t normalized_rx_power; - /// target rx power - int32_t target_rx_power; - - /// num rx pdu - uint32_t num_pdu_rx[NB_RB_MAX]; - /// num bytes rx - uint32_t num_bytes_rx[NB_RB_MAX]; - /// instantaneous rx throughput for each TTI - // uint32_t tti_goodput[NB_RB_MAX]; - /// errors - uint32_t num_errors_rx; - - uint64_t overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes_rx; - // - uint32_t ulsch_bitrate; - //total - uint32_t total_ulsch_bitrate; - /// overall - /// MAC pdu bytes - uint64_t pdu_bytes_rx; - /// total MAC pdu bytes - uint64_t total_pdu_bytes_rx; - /// total num pdu - uint32_t total_num_pdus_rx; - /// num of error pdus - uint32_t total_num_errors_rx; + /// CRNTI of UE + rnti_t crnti; ///user id (rnti) of connected UEs + // rrc status + uint8_t rrc_status; + /// harq pid + uint8_t harq_pid; + /// harq rounf + uint8_t harq_round; + /// total available number of PRBs for a new transmission + uint16_t rbs_used; + /// total available number of PRBs for a retransmission + uint16_t rbs_used_retx; + /// total nccc used for a new transmission: num control channel element + uint16_t ncce_used; + /// total avilable nccc for a retransmission: num control channel element + uint16_t ncce_used_retx; + + // mcs1 before the rate adaptaion + uint8_t dlsch_mcs1; + /// Target mcs2 after rate-adaptation + uint8_t dlsch_mcs2; + // current TBS with mcs2 + uint32_t TBS; + // total TBS with mcs2 + // uint32_t total_TBS; + // total rb used for a new transmission + uint32_t total_rbs_used; + // total rb used for retransmission + uint32_t total_rbs_used_retx; + + /// TX + /// Num pkt + uint32_t num_pdu_tx[NB_RB_MAX]; + /// num bytes + uint32_t num_bytes_tx[NB_RB_MAX]; + /// num retransmission / harq + uint32_t num_retransmission; + /// instantaneous tx throughput for each TTI + // uint32_t tti_throughput[NB_RB_MAX]; + + /// overall + // + uint32_t dlsch_bitrate; + //total + uint32_t total_dlsch_bitrate; + /// headers+ CE + padding bytes for a MAC PDU + uint64_t overhead_bytes; + /// headers+ CE + padding bytes for a MAC PDU + uint64_t total_overhead_bytes; + /// headers+ CE + padding bytes for a MAC PDU + uint64_t avg_overhead_bytes; + // MAC multiplexed payload + uint64_t total_sdu_bytes; + // total MAC pdu bytes + uint64_t total_pdu_bytes; + + // total num pdu + uint32_t total_num_pdus; + // + // uint32_t avg_pdu_size; + + /// RX + + /// PUCCH1a/b power (dBm) + int32_t Po_PUCCH_dBm; + /// Indicator that Po_PUCCH has been updated by PHY + int32_t Po_PUCCH_update; + /// Uplink measured RSSI + int32_t UL_rssi; + /// preassigned mcs after rate adaptation + uint8_t ulsch_mcs1; + /// adjusted mcs + uint8_t ulsch_mcs2; + + /// estimated average pdu inter-departure time + uint32_t avg_pdu_idt; + /// estimated average pdu size + uint32_t avg_pdu_ps; + /// + uint32_t aggregated_pdu_size; + uint32_t aggregated_pdu_arrival; + + /// uplink transport block size + uint32_t ulsch_TBS; + + /// total rb used for a new uplink transmission + uint32_t num_retransmission_rx; + /// total rb used for a new uplink transmission + uint32_t rbs_used_rx; + /// total rb used for a new uplink retransmission + uint32_t rbs_used_retx_rx; + /// total rb used for a new uplink transmission + uint32_t total_rbs_used_rx; + /// normalized rx power + int32_t normalized_rx_power; + /// target rx power + int32_t target_rx_power; + + /// num rx pdu + uint32_t num_pdu_rx[NB_RB_MAX]; + /// num bytes rx + uint32_t num_bytes_rx[NB_RB_MAX]; + /// instantaneous rx throughput for each TTI + // uint32_t tti_goodput[NB_RB_MAX]; + /// errors + uint32_t num_errors_rx; + + uint64_t overhead_bytes_rx; + /// headers+ CE + padding bytes for a MAC PDU + uint64_t total_overhead_bytes_rx; + /// headers+ CE + padding bytes for a MAC PDU + uint64_t avg_overhead_bytes_rx; + // + uint32_t ulsch_bitrate; + //total + uint32_t total_ulsch_bitrate; + /// overall + /// MAC pdu bytes + uint64_t pdu_bytes_rx; + /// total MAC pdu bytes + uint64_t total_pdu_bytes_rx; + /// total num pdu + uint32_t total_num_pdus_rx; + /// num of error pdus + uint32_t total_num_errors_rx; } eNB_UE_STATS; /*! \brief eNB template for UE context information */ typedef struct { - /// C-RNTI of UE - rnti_t rnti; - /// NDI from last scheduling - uint8_t oldNDI[8]; - /// mcs1 from last scheduling - uint8_t oldmcs1[8]; - /// mcs2 from last scheduling - uint8_t oldmcs2[8]; - /// NDI from last UL scheduling - uint8_t oldNDI_UL[8]; - /// mcs from last UL scheduling - uint8_t mcs_UL[8]; - /// TBS from last UL scheduling - uint8_t TBS_UL[8]; - /// Flag to indicate UL has been scheduled at least once - boolean_t ul_active; - /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) - boolean_t configured; - - /// MCS from last scheduling - uint8_t mcs[8]; - - /// TPC from last scheduling - uint8_t oldTPC[8]; - - // PHY interface info - - /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation) - uint16_t nb_rb[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t nb_rb_ul[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t first_rb_ul[8]; // num_max_harq - - /// Cyclic shift for DMRS after scheduling - uint16_t cshift[8]; // num_max_harq - - /// Number of Allocated RBs by the ulsch preprocessor - uint8_t pre_allocated_nb_rb_ul; - - /// index of Allocated RBs by the ulsch preprocessor - int8_t pre_allocated_rb_table_index_ul; - - /// total allocated RBs - int8_t total_allocated_rbs; - - /// pre-assigned MCS by the ulsch preprocessor - uint8_t pre_assigned_mcs_ul; - - /// assigned MCS by the ulsch scheduler - uint8_t assigned_mcs_ul; - - /// DL DAI - uint8_t DAI; - - /// UL DAI - uint8_t DAI_ul[10]; - - /// UL Scheduling Request Received - uint8_t ul_SR; - - ///Resource Block indication for each sub-band in MU-MIMO - uint8_t rballoc_subband[8][50]; - - // Logical channel info for link with RLC - - /// Last received UE BSR info for each logical channel group id - uint8_t bsr_info[MAX_NUM_LCGID]; - - /// LCGID mapping - long lcgidmap[11]; - - /// phr information - int8_t phr_info; - - /// phr information - int8_t phr_info_configured; - - ///dl buffer info - uint32_t dl_buffer_info[MAX_NUM_LCID]; - /// total downlink buffer info - uint32_t dl_buffer_total; - /// total downlink pdus - uint32_t dl_pdus_total; - /// downlink pdus for each LCID - uint32_t dl_pdus_in_buffer[MAX_NUM_LCID]; - /// creation time of the downlink buffer head for each LCID - uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID]; - /// maximum creation time of the downlink buffer head across all LCID - uint32_t dl_buffer_head_sdu_creation_time_max; - /// a flag indicating that the downlink head SDU is segmented - uint8_t dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID]; - /// size of remaining size to send for the downlink head SDU - uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID]; - - /// total uplink buffer size - uint32_t ul_total_buffer; - /// uplink buffer creation time for each LCID - uint32_t ul_buffer_creation_time[MAX_NUM_LCGID]; - /// maximum uplink buffer creation time across all the LCIDs - uint32_t ul_buffer_creation_time_max; - /// uplink buffer size per LCID - uint32_t ul_buffer_info[MAX_NUM_LCGID]; - - /// UE tx power - int32_t ue_tx_power; + /// C-RNTI of UE + rnti_t rnti; + /// NDI from last scheduling + uint8_t oldNDI[8]; + /// mcs1 from last scheduling + uint8_t oldmcs1[8]; + /// mcs2 from last scheduling + uint8_t oldmcs2[8]; + /// NDI from last UL scheduling + uint8_t oldNDI_UL[8]; + /// mcs from last UL scheduling + uint8_t mcs_UL[8]; + /// TBS from last UL scheduling + uint8_t TBS_UL[8]; + /// Flag to indicate UL has been scheduled at least once + boolean_t ul_active; + /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) + boolean_t configured; + + /// MCS from last scheduling + uint8_t mcs[8]; + + /// TPC from last scheduling + uint8_t oldTPC[8]; + + // PHY interface info + + /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation) + uint16_t nb_rb[8]; // num_max_harq + + /// Number of Allocated RBs for UL after scheduling + uint16_t nb_rb_ul[8]; // num_max_harq + + /// Number of Allocated RBs for UL after scheduling + uint16_t first_rb_ul[8]; // num_max_harq + + /// Cyclic shift for DMRS after scheduling + uint16_t cshift[8]; // num_max_harq + + /// Number of Allocated RBs by the ulsch preprocessor + uint8_t pre_allocated_nb_rb_ul; + + /// index of Allocated RBs by the ulsch preprocessor + int8_t pre_allocated_rb_table_index_ul; + + /// total allocated RBs + int8_t total_allocated_rbs; + + /// pre-assigned MCS by the ulsch preprocessor + uint8_t pre_assigned_mcs_ul; + + /// assigned MCS by the ulsch scheduler + uint8_t assigned_mcs_ul; + + /// DL DAI + uint8_t DAI; + + /// UL DAI + uint8_t DAI_ul[10]; + + /// UL Scheduling Request Received + uint8_t ul_SR; + + ///Resource Block indication for each sub-band in MU-MIMO + uint8_t rballoc_subband[8][50]; + + // Logical channel info for link with RLC + + /// Last received UE BSR info for each logical channel group id + uint8_t bsr_info[MAX_NUM_LCGID]; + + /// LCGID mapping + long lcgidmap[11]; + + /// phr information + int8_t phr_info; + + /// phr information + int8_t phr_info_configured; + + ///dl buffer info + uint32_t dl_buffer_info[MAX_NUM_LCID]; + /// total downlink buffer info + uint32_t dl_buffer_total; + /// total downlink pdus + uint32_t dl_pdus_total; + /// downlink pdus for each LCID + uint32_t dl_pdus_in_buffer[MAX_NUM_LCID]; + /// creation time of the downlink buffer head for each LCID + uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID]; + /// maximum creation time of the downlink buffer head across all LCID + uint32_t dl_buffer_head_sdu_creation_time_max; + /// a flag indicating that the downlink head SDU is segmented + uint8_t dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID]; + /// size of remaining size to send for the downlink head SDU + uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID]; + + /// total uplink buffer size + uint32_t ul_total_buffer; + /// uplink buffer creation time for each LCID + uint32_t ul_buffer_creation_time[MAX_NUM_LCGID]; + /// maximum uplink buffer creation time across all the LCIDs + uint32_t ul_buffer_creation_time_max; + /// uplink buffer size per LCID + uint32_t ul_buffer_info[MAX_NUM_LCGID]; + + /// UE tx power + int32_t ue_tx_power; - /// stores the frame where the last TPC was transmitted - uint32_t pusch_tpc_tx_frame; - uint32_t pusch_tpc_tx_subframe; - uint32_t pucch_tpc_tx_frame; - uint32_t pucch_tpc_tx_subframe; + /// stores the frame where the last TPC was transmitted + uint32_t pusch_tpc_tx_frame; + uint32_t pusch_tpc_tx_subframe; + uint32_t pucch_tpc_tx_frame; + uint32_t pucch_tpc_tx_subframe; #ifdef LOCALIZATION - eNB_UE_estimated_distances distance; + eNB_UE_estimated_distances distance; #endif #ifdef Rel14 - uint8_t rach_resource_type; - uint16_t mpdcch_repetition_cnt; - frame_t Msg2_frame; + uint8_t rach_resource_type; + uint16_t mpdcch_repetition_cnt; + frame_t Msg2_frame; #endif - sub_frame_t Msg2_subframe; + sub_frame_t Msg2_subframe; - PhysicalConfigDedicated_t *physicalConfigDedicated; + PhysicalConfigDedicated_t *physicalConfigDedicated; } UE_TEMPLATE; /*! \brief scheduling control information set through an API (not used)*/ typedef struct { - ///UL transmission bandwidth in RBs - uint8_t ul_bandwidth[MAX_NUM_LCID]; - ///DL transmission bandwidth in RBs - uint8_t dl_bandwidth[MAX_NUM_LCID]; - - //To do GBR bearer - uint8_t min_ul_bandwidth[MAX_NUM_LCID]; - - uint8_t min_dl_bandwidth[MAX_NUM_LCID]; - - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateDL; - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateUL; - ///CQI scheduling interval in subframes. - uint16_t cqiSchedInterval; - ///Contention resolution timer used during random access - uint8_t mac_ContentionResolutionTimer; - - uint16_t max_allowed_rbs[MAX_NUM_LCID]; - - uint8_t max_mcs[MAX_NUM_LCID]; - - uint16_t priority[MAX_NUM_LCID]; - - // resource scheduling information - - /// Current DL harq round per harq_pid on each CC - uint8_t round[MAX_NUM_CCs][10]; - /// Current Active TBs per harq_pid on each CC - uint8_t tbcnt[MAX_NUM_CCs][10]; - /// Current UL harq round per harq_pid on each CC - uint8_t round_UL[MAX_NUM_CCs][8]; - uint8_t dl_pow_off[MAX_NUM_CCs]; - uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; - unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; - uint16_t ta_timer; - int16_t ta_update; - uint16_t ul_consecutive_errors; - int32_t context_active_timer; - int32_t cqi_req_timer; - int32_t ul_inactivity_timer; - int32_t ul_failure_timer; - int32_t ul_scheduled; - int32_t ra_pdcch_order_sent; - int32_t ul_out_of_sync; - int32_t phr_received; - uint8_t periodic_ri_received[NFAPI_CC_MAX]; - uint8_t aperiodic_ri_received[NFAPI_CC_MAX]; - uint8_t pucch1_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch1_snr[NFAPI_CC_MAX]; - uint8_t pucch2_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch2_snr[NFAPI_CC_MAX]; - uint8_t pucch3_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch3_snr[NFAPI_CC_MAX]; - uint8_t pusch_snr[NFAPI_CC_MAX]; - uint16_t feedback_cnt[NFAPI_CC_MAX]; - uint16_t timing_advance; - uint16_t timing_advance_r9; - uint8_t periodic_wideband_cqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_spatial_diffcqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t periodic_subband_cqi[NFAPI_CC_MAX][16]; - uint8_t periodic_subband_spatial_diffcqi[NFAPI_CC_MAX][16]; - uint8_t aperiodic_subband_cqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_pmi[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_cqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_wideband_cqi0[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_cqi1[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi1[NFAPI_CC_MAX]; - uint8_t dl_cqi[NFAPI_CC_MAX]; + ///UL transmission bandwidth in RBs + uint8_t ul_bandwidth[MAX_NUM_LCID]; + ///DL transmission bandwidth in RBs + uint8_t dl_bandwidth[MAX_NUM_LCID]; + + //To do GBR bearer + uint8_t min_ul_bandwidth[MAX_NUM_LCID]; + + uint8_t min_dl_bandwidth[MAX_NUM_LCID]; + + ///aggregated bit rate of non-gbr bearer per UE + uint64_t ue_AggregatedMaximumBitrateDL; + ///aggregated bit rate of non-gbr bearer per UE + uint64_t ue_AggregatedMaximumBitrateUL; + ///CQI scheduling interval in subframes. + uint16_t cqiSchedInterval; + ///Contention resolution timer used during random access + uint8_t mac_ContentionResolutionTimer; + + uint16_t max_allowed_rbs[MAX_NUM_LCID]; + + uint8_t max_mcs[MAX_NUM_LCID]; + + uint16_t priority[MAX_NUM_LCID]; + + // resource scheduling information + + /// Current DL harq round per harq_pid on each CC + uint8_t round[MAX_NUM_CCs][10]; + /// Current Active TBs per harq_pid on each CC + uint8_t tbcnt[MAX_NUM_CCs][10]; + /// Current UL harq round per harq_pid on each CC + uint8_t round_UL[MAX_NUM_CCs][8]; + uint8_t dl_pow_off[MAX_NUM_CCs]; + uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; + unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; + uint16_t ta_timer; + int16_t ta_update; + uint16_t ul_consecutive_errors; + int32_t context_active_timer; + int32_t cqi_req_timer; + int32_t ul_inactivity_timer; + int32_t ul_failure_timer; + int32_t ul_scheduled; + int32_t ra_pdcch_order_sent; + int32_t ul_out_of_sync; + int32_t phr_received; + uint8_t periodic_ri_received[NFAPI_CC_MAX]; + uint8_t aperiodic_ri_received[NFAPI_CC_MAX]; + uint8_t pucch1_cqi_update[NFAPI_CC_MAX]; + uint8_t pucch1_snr[NFAPI_CC_MAX]; + uint8_t pucch2_cqi_update[NFAPI_CC_MAX]; + uint8_t pucch2_snr[NFAPI_CC_MAX]; + uint8_t pucch3_cqi_update[NFAPI_CC_MAX]; + uint8_t pucch3_snr[NFAPI_CC_MAX]; + uint8_t pusch_snr[NFAPI_CC_MAX]; + uint16_t feedback_cnt[NFAPI_CC_MAX]; + uint16_t timing_advance; + uint16_t timing_advance_r9; + uint8_t periodic_wideband_cqi[NFAPI_CC_MAX]; + uint8_t periodic_wideband_spatial_diffcqi[NFAPI_CC_MAX]; + uint8_t periodic_wideband_pmi[NFAPI_CC_MAX]; + uint8_t periodic_subband_cqi[NFAPI_CC_MAX][16]; + uint8_t periodic_subband_spatial_diffcqi[NFAPI_CC_MAX][16]; + uint8_t aperiodic_subband_cqi0[NFAPI_CC_MAX][25]; + uint8_t aperiodic_subband_pmi[NFAPI_CC_MAX][25]; + uint8_t aperiodic_subband_diffcqi0[NFAPI_CC_MAX][25]; + uint8_t aperiodic_subband_cqi1[NFAPI_CC_MAX][25]; + uint8_t aperiodic_subband_diffcqi1[NFAPI_CC_MAX][25]; + uint8_t aperiodic_wideband_cqi0[NFAPI_CC_MAX]; + uint8_t aperiodic_wideband_pmi[NFAPI_CC_MAX]; + uint8_t aperiodic_wideband_cqi1[NFAPI_CC_MAX]; + uint8_t aperiodic_wideband_pmi1[NFAPI_CC_MAX]; + uint8_t dl_cqi[NFAPI_CC_MAX]; } UE_sched_ctrl; /*! \brief eNB template for the Random access information */ typedef struct { - /// Flag to indicate this process is active - boolean_t RA_active; - /// Size of DCI for RA-Response (bytes) - uint8_t RA_dci_size_bytes1; - /// Size of DCI for RA-Response (bits) - uint8_t RA_dci_size_bits1; - /// Actual DCI to transmit for RA-Response - uint8_t RA_alloc_pdu1[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for RA-Response (should be 1A) - uint8_t RA_dci_fmt1; - /// Size of DCI for Msg4/ContRes (bytes) - uint8_t RA_dci_size_bytes2; - /// Size of DCI for Msg4/ContRes (bits) - uint8_t RA_dci_size_bits2; - /// Actual DCI to transmit for Msg4/ContRes - uint8_t RA_alloc_pdu2[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for Msg4/ContRes (should be 1A) - uint8_t RA_dci_fmt2; - /// Flag to indicate the eNB should generate RAR. This is triggered by detection of PRACH - uint8_t generate_rar; - /// Subframe where preamble was received - uint8_t preamble_subframe; - /// Subframe where Msg2 is to be sent - uint8_t Msg2_subframe; - /// Frame where Msg2 is to be sent - frame_t Msg2_frame; - /// Subframe where Msg3 is to be sent - sub_frame_t Msg3_subframe; - /// Frame where Msg3 is to be sent - frame_t Msg3_frame; - /// Subframe where Msg4 is to be sent - sub_frame_t Msg4_subframe; - /// Frame where Msg4 is to be sent - frame_t Msg4_frame; - /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. - uint8_t generate_Msg4; - /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. - uint8_t wait_ack_Msg4; - /// harq_pid used for Msg4 transmission - uint8_t harq_pid; - /// UE RNTI allocated during RAR - rnti_t rnti; - /// RA RNTI allocated from received PRACH - uint16_t RA_rnti; - /// Received preamble_index - uint8_t preamble_index; - /// Received UE Contention Resolution Identifier - uint8_t cont_res_id[6]; - /// Timing offset indicated by PHY - int16_t timing_offset; - /// Timeout for RRC connection - int16_t RRC_timer; - /// Msg3 first RB - uint8_t msg3_first_rb; - /// Msg3 number of RB - uint8_t msg3_nb_rb; - /// Msg3 MCS - uint8_t msg3_mcs; - /// Msg3 TPC command - uint8_t msg3_TPC; - /// Msg3 ULdelay command - uint8_t msg3_ULdelay; - /// Msg3 cqireq command - uint8_t msg3_cqireq; - /// Round of Msg3 HARQ - uint8_t msg3_round; - /// TBS used for Msg4 - int msg4_TBsize; - /// MCS used for Msg4 - int msg4_mcs; + /// Flag to indicate this process is active + RA_state state; + /// Subframe where preamble was received + uint8_t preamble_subframe; + /// Subframe where Msg2 is to be sent + uint8_t Msg2_subframe; + /// Frame where Msg2 is to be sent + frame_t Msg2_frame; + /// Subframe where Msg3 is to be sent + sub_frame_t Msg3_subframe; + /// Frame where Msg3 is to be sent + frame_t Msg3_frame; + /// Subframe where Msg4 is to be sent + sub_frame_t Msg4_subframe; + /// Frame where Msg4 is to be sent + frame_t Msg4_frame; + /// harq_pid used for Msg4 transmission + uint8_t harq_pid; + /// UE RNTI allocated during RAR + rnti_t rnti; + /// RA RNTI allocated from received PRACH + uint16_t RA_rnti; + /// Received preamble_index + uint8_t preamble_index; + /// Received UE Contention Resolution Identifier + uint8_t cont_res_id[6]; + /// Timing offset indicated by PHY + int16_t timing_offset; + /// Timeout for RRC connection + int16_t RRC_timer; + /// Msg3 first RB + uint8_t msg3_first_rb; + /// Msg3 number of RB + uint8_t msg3_nb_rb; + /// Msg3 MCS + uint8_t msg3_mcs; + /// Msg3 TPC command + uint8_t msg3_TPC; + /// Msg3 ULdelay command + uint8_t msg3_ULdelay; + /// Msg3 cqireq command + uint8_t msg3_cqireq; + /// Round of Msg3 HARQ + uint8_t msg3_round; + /// TBS used for Msg4 + int msg4_TBsize; + /// MCS used for Msg4 + int msg4_mcs; #ifdef Rel14 - uint8_t rach_resource_type; - uint8_t msg2_mpdcch_repetition_cnt; - uint8_t msg4_mpdcch_repetition_cnt; - uint8_t msg2_narrowband; - uint8_t msg34_narrowband; + uint8_t rach_resource_type; + uint8_t msg2_mpdcch_repetition_cnt; + uint8_t msg4_mpdcch_repetition_cnt; + uint8_t msg2_narrowband; + uint8_t msg34_narrowband; #endif -} RA_TEMPLATE; +} RA_t; /*! \brief subband bitmap confguration (for ALU icic algo purpose), in test phase */ typedef struct { - uint8_t sbmap[NUMBER_OF_SUBBANDS_MAX]; //13 = number of SB MAX for 100 PRB - uint8_t periodicity; - uint8_t first_subframe; - uint8_t sb_size; - uint8_t nb_active_sb; + uint8_t sbmap[NUMBER_OF_SUBBANDS_MAX]; //13 = number of SB MAX for 100 PRB + uint8_t periodicity; + uint8_t first_subframe; + uint8_t sb_size; + uint8_t nb_active_sb; } SBMAP_CONF; -/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ +/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ typedef struct { - /// Dedicated information for UEs - struct PhysicalConfigDedicated *physicalConfigDedicated[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DLSCH pdu - DLSCH_PDU DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection parameters for UEs - UE_TEMPLATE UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection for RA processes - int pCC_id[NUMBER_OF_UE_MAX]; - /// sorted downlink component carrier for the scheduler - int ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - int numactiveCCs[NUMBER_OF_UE_MAX]; - /// sorted uplink component carrier for the scheduler - int ordered_ULCCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of uplink active component carrier - int numactiveULCCs[NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - uint8_t dl_CC_bitmap[NUMBER_OF_UE_MAX]; - /// eNB to UE statistics - eNB_UE_STATS eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// scheduling control info - UE_sched_ctrl UE_sched_ctrl[NUMBER_OF_UE_MAX]; - int next[NUMBER_OF_UE_MAX]; - int head; - int next_ul[NUMBER_OF_UE_MAX]; - int head_ul; - int avail; - int num_UEs; - boolean_t active[NUMBER_OF_UE_MAX]; + /// Dedicated information for UEs + struct PhysicalConfigDedicated + *physicalConfigDedicated[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + /// DLSCH pdu + DLSCH_PDU DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX]; + /// DCI template and MAC connection parameters for UEs + UE_TEMPLATE UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + /// DCI template and MAC connection for RA processes + int pCC_id[NUMBER_OF_UE_MAX]; + /// sorted downlink component carrier for the scheduler + int ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + /// number of downlink active component carrier + int numactiveCCs[NUMBER_OF_UE_MAX]; + /// sorted uplink component carrier for the scheduler + int ordered_ULCCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + /// number of uplink active component carrier + int numactiveULCCs[NUMBER_OF_UE_MAX]; + /// number of downlink active component carrier + uint8_t dl_CC_bitmap[NUMBER_OF_UE_MAX]; + /// eNB to UE statistics + eNB_UE_STATS eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + /// scheduling control info + UE_sched_ctrl UE_sched_ctrl[NUMBER_OF_UE_MAX]; + int next[NUMBER_OF_UE_MAX]; + int head; + int next_ul[NUMBER_OF_UE_MAX]; + int head_ul; + int avail; + int num_UEs; + boolean_t active[NUMBER_OF_UE_MAX]; } UE_list_t; -/*! \brief eNB common channels */ +/*! \brief eNB common channels */ typedef struct { - int physCellId; - int p_eNB; - int Ncp; - int eutra_band; - uint32_t dl_CarrierFreq; - BCCH_BCH_Message_t *mib; - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; + int physCellId; + int p_eNB; + int Ncp; + int eutra_band; + uint32_t dl_CarrierFreq; + BCCH_BCH_Message_t *mib; + RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; #ifdef Rel14 - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR; + RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR; #endif - TDD_Config_t *tdd_Config; - SchedulingInfoList_t *schedulingInfoList; - ARFCN_ValueEUTRA_t ul_CarrierFreq; - long ul_Bandwidth; - /// Outgoing MIB PDU for PHY - MIB_PDU MIB_pdu; - /// Outgoing BCCH pdu for PHY - BCCH_PDU BCCH_pdu; - /// Outgoing BCCH DCI allocation - uint32_t BCCH_alloc_pdu; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Template for RA computations - RA_TEMPLATE RA_template[NB_RA_PROC_MAX]; - /// VRB map for common channels - uint8_t vrb_map[100]; - /// VRB map for common channels and retransmissions by PHICH - uint8_t vrb_map_UL[100]; - /// MBSFN SubframeConfig - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; + TDD_Config_t *tdd_Config; + SchedulingInfoList_t *schedulingInfoList; + ARFCN_ValueEUTRA_t ul_CarrierFreq; + long ul_Bandwidth; + /// Outgoing MIB PDU for PHY + MIB_PDU MIB_pdu; + /// Outgoing BCCH pdu for PHY + BCCH_PDU BCCH_pdu; + /// Outgoing BCCH DCI allocation + uint32_t BCCH_alloc_pdu; + /// Outgoing CCCH pdu for PHY + CCCH_PDU CCCH_pdu; + /// Outgoing RAR pdu for PHY + RAR_PDU RAR_pdu; + /// Template for RA computations + RA_t ra[NB_RA_PROC_MAX]; + /// VRB map for common channels + uint8_t vrb_map[100]; + /// VRB map for common channels and retransmissions by PHICH + uint8_t vrb_map_UL[100]; + /// MBSFN SubframeConfig + struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; + /// number of subframe allocation pattern available for MBSFN sync area + uint8_t num_sf_allocation_pattern; #if defined(Rel10) || defined(Rel14) - /// MBMS Flag - uint8_t MBMS_flag; - /// Outgoing MCCH pdu for PHY - MCCH_PDU MCCH_pdu; - /// MCCH active flag - uint8_t msi_active; - /// MCCH active flag - uint8_t mcch_active; - /// MTCH active flag - uint8_t mtch_active; - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MBMS session info list - struct MBMS_SessionInfoList_r9 *mbms_SessionList[MAX_PMCH_perMBSFN]; - /// Outgoing MCH pdu for PHY - MCH_PDU MCH_pdu; + /// MBMS Flag + uint8_t MBMS_flag; + /// Outgoing MCCH pdu for PHY + MCCH_PDU MCCH_pdu; + /// MCCH active flag + uint8_t msi_active; + /// MCCH active flag + uint8_t mcch_active; + /// MTCH active flag + uint8_t mtch_active; + /// number of active MBSFN area + uint8_t num_active_mbsfn_area; + /// MBSFN Area Info + struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; + /// PMCH Config + struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; + /// MBMS session info list + struct MBMS_SessionInfoList_r9 *mbms_SessionList[MAX_PMCH_perMBSFN]; + /// Outgoing MCH pdu for PHY + MCH_PDU MCH_pdu; #endif #ifdef Rel14 - /// Rel13 parameters from SIB1 - SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext; - /// Counter for SIB1-BR scheduling - int SIB1_BR_cnt; - /// Outgoing BCCH-BR pdu for PHY - BCCH_PDU BCCH_BR_pdu[20]; + /// Rel13 parameters from SIB1 + SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext; + /// Counter for SIB1-BR scheduling + int SIB1_BR_cnt; + /// Outgoing BCCH-BR pdu for PHY + BCCH_PDU BCCH_BR_pdu[20]; #endif } COMMON_channels_t; -/*! \brief top level eNB MAC structure */ +/*! \brief top level eNB MAC structure */ typedef struct eNB_MAC_INST_s { - /// Ethernet parameters for northbound midhaul interface - eth_params_t eth_params_n; - /// Ethernet parameters for fronthaul interface - eth_params_t eth_params_s; - /// - module_id_t Mod_id; - /// frame counter - frame_t frame; - /// subframe counter - sub_frame_t subframe; - /// Pointer to IF module instance for PHY - IF_Module_t *if_inst; - /// Common cell resources - COMMON_channels_t common_channels[MAX_NUM_CCs]; - /// current PDU index (BCH,MCH,DLSCH) - uint16_t pdu_index[MAX_NUM_CCs]; - - /// NFAPI Config Request Structure - nfapi_config_request_t config[MAX_NUM_CCs]; - /// Preallocated DL pdu list - nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_CCs][MAX_NUM_DL_PDU]; - /// NFAPI DL Config Request Structure - nfapi_dl_config_request_t DL_req[MAX_NUM_CCs]; - /// Preallocated UL pdu list - nfapi_ul_config_request_pdu_t ul_config_pdu_list[MAX_NUM_CCs][MAX_NUM_UL_PDU]; - /// Preallocated UL pdu list for ULSCH (n+k delay) - nfapi_ul_config_request_pdu_t ul_config_pdu_list_tmp[MAX_NUM_CCs][10][MAX_NUM_UL_PDU]; - /// NFAPI UL Config Request Structure, send to L1 4 subframes before processing takes place - nfapi_ul_config_request_t UL_req[MAX_NUM_CCs]; - /// NFAPI "Temporary" UL Config Request Structure, holds future UL_config requests - nfapi_ul_config_request_t UL_req_tmp[MAX_NUM_CCs][10]; - /// Preallocated HI_DCI0 pdu list - nfapi_hi_dci0_request_pdu_t hi_dci0_pdu_list[MAX_NUM_CCs][MAX_NUM_HI_DCI0_PDU]; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_hi_dci0_request_t HI_DCI0_req[MAX_NUM_CCs]; - /// Prealocated TX pdu list - nfapi_tx_request_pdu_t tx_request_pdu[MAX_NUM_CCs][MAX_NUM_TX_REQUEST_PDU]; - /// NFAPI DL PDU structure - nfapi_tx_request_t TX_req[MAX_NUM_CCs]; - /// UL handle - uint32_t ul_handle; - UE_list_t UE_list; - - ///subband bitmap configuration - SBMAP_CONF sbmap_conf; - /// CCE table used to build DCI scheduling information - int CCE_table[MAX_NUM_CCs][800]; - /// active flag for Other lcid - uint8_t lcid_active[NB_RB_MAX]; - /// eNB stats - eNB_STATS eNB_stats[MAX_NUM_CCs]; - // MAC function execution peformance profiler - /// processing time of eNB scheduler - time_stats_t eNB_scheduler; - /// processing time of eNB scheduler for SI - time_stats_t schedule_si; - /// processing time of eNB scheduler for Random access - time_stats_t schedule_ra; - /// processing time of eNB ULSCH scheduler - time_stats_t schedule_ulsch; - /// processing time of eNB DCI generation - time_stats_t fill_DLSCH_dci; - /// processing time of eNB MAC preprocessor - time_stats_t schedule_dlsch_preprocessor; - /// processing time of eNB DLSCH scheduler - time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor - /// processing time of eNB MCH scheduler - time_stats_t schedule_mch; - /// processing time of eNB ULSCH reception - time_stats_t rx_ulsch_sdu; // include rlc_data_ind + /// Ethernet parameters for northbound midhaul interface + eth_params_t eth_params_n; + /// Ethernet parameters for fronthaul interface + eth_params_t eth_params_s; + /// + module_id_t Mod_id; + /// frame counter + frame_t frame; + /// subframe counter + sub_frame_t subframe; + /// Pointer to IF module instance for PHY + IF_Module_t *if_inst; + /// Common cell resources + COMMON_channels_t common_channels[MAX_NUM_CCs]; + /// current PDU index (BCH,MCH,DLSCH) + uint16_t pdu_index[MAX_NUM_CCs]; + + /// NFAPI Config Request Structure + nfapi_config_request_t config[MAX_NUM_CCs]; + /// Preallocated DL pdu list + nfapi_dl_config_request_pdu_t + dl_config_pdu_list[MAX_NUM_CCs][MAX_NUM_DL_PDU]; + /// NFAPI DL Config Request Structure + nfapi_dl_config_request_t DL_req[MAX_NUM_CCs]; + /// Preallocated UL pdu list + nfapi_ul_config_request_pdu_t + ul_config_pdu_list[MAX_NUM_CCs][MAX_NUM_UL_PDU]; + /// Preallocated UL pdu list for ULSCH (n+k delay) + nfapi_ul_config_request_pdu_t + ul_config_pdu_list_tmp[MAX_NUM_CCs][10][MAX_NUM_UL_PDU]; + /// NFAPI UL Config Request Structure, send to L1 4 subframes before processing takes place + nfapi_ul_config_request_t UL_req[MAX_NUM_CCs]; + /// NFAPI "Temporary" UL Config Request Structure, holds future UL_config requests + nfapi_ul_config_request_t UL_req_tmp[MAX_NUM_CCs][10]; + /// Preallocated HI_DCI0 pdu list + nfapi_hi_dci0_request_pdu_t + hi_dci0_pdu_list[MAX_NUM_CCs][MAX_NUM_HI_DCI0_PDU]; + /// NFAPI HI/DCI0 Config Request Structure + nfapi_hi_dci0_request_t HI_DCI0_req[MAX_NUM_CCs]; + /// Prealocated TX pdu list + nfapi_tx_request_pdu_t + tx_request_pdu[MAX_NUM_CCs][MAX_NUM_TX_REQUEST_PDU]; + /// NFAPI DL PDU structure + nfapi_tx_request_t TX_req[MAX_NUM_CCs]; + /// UL handle + uint32_t ul_handle; + UE_list_t UE_list; + + ///subband bitmap configuration + SBMAP_CONF sbmap_conf; + /// CCE table used to build DCI scheduling information + int CCE_table[MAX_NUM_CCs][800]; + /// active flag for Other lcid + uint8_t lcid_active[NB_RB_MAX]; + /// eNB stats + eNB_STATS eNB_stats[MAX_NUM_CCs]; + // MAC function execution peformance profiler + /// processing time of eNB scheduler + time_stats_t eNB_scheduler; + /// processing time of eNB scheduler for SI + time_stats_t schedule_si; + /// processing time of eNB scheduler for Random access + time_stats_t schedule_ra; + /// processing time of eNB ULSCH scheduler + time_stats_t schedule_ulsch; + /// processing time of eNB DCI generation + time_stats_t fill_DLSCH_dci; + /// processing time of eNB MAC preprocessor + time_stats_t schedule_dlsch_preprocessor; + /// processing time of eNB DLSCH scheduler + time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor + /// processing time of eNB MCH scheduler + time_stats_t schedule_mch; + /// processing time of eNB ULSCH reception + time_stats_t rx_ulsch_sdu; // include rlc_data_ind } eNB_MAC_INST; /* * UE part - */ + */ typedef enum { - TYPE0, - TYPE1, - TYPE1A, - TYPE2, - TYPE2A, - TYPEUESPEC + TYPE0, + TYPE1, + TYPE1A, + TYPE2, + TYPE2A, + TYPEUESPEC } MPDCCH_TYPES_t; /*!\brief UE layer 2 status */ typedef enum { - CONNECTION_OK=0, - CONNECTION_LOST, - PHY_RESYNCH, - PHY_HO_PRACH + CONNECTION_OK = 0, + CONNECTION_LOST, + PHY_RESYNCH, + PHY_HO_PRACH } UE_L2_STATE_t; /*!\brief UE scheduling info */ typedef struct { - /// buffer status for each lcgid - uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology - /// keep the number of bytes in rlc buffer for each lcgid - int32_t BSR_bytes[MAX_NUM_LCGID]; - /// after multiplexing buffer remain for each lcid - int32_t LCID_buffer_remain[MAX_NUM_LCID]; - /// sum of all lcid buffer size - uint16_t All_lcid_buffer_size_lastTTI; - /// buffer status for each lcid - uint8_t LCID_status[MAX_NUM_LCID]; - /// SR pending as defined in 36.321 - uint8_t SR_pending; - /// SR_COUNTER as defined in 36.321 - uint16_t SR_COUNTER; - /// logical channel group ide for each LCID - uint8_t LCGID[MAX_NUM_LCID]; - /// retxBSR-Timer, default value is sf2560 - uint16_t retxBSR_Timer; - /// retxBSR_SF, number of subframe before triggering a regular BSR - uint16_t retxBSR_SF; - /// periodicBSR-Timer, default to infinity - uint16_t periodicBSR_Timer; - /// periodicBSR_SF, number of subframe before triggering a periodic BSR - uint16_t periodicBSR_SF; - /// default value is 0: not configured - uint16_t sr_ProhibitTimer; - /// sr ProhibitTime running - uint8_t sr_ProhibitTimer_Running; - /// default value to n5 - uint16_t maxHARQ_Tx; - /// default value is false - uint16_t ttiBundling; - /// default value is release - struct DRX_Config *drx_config; - /// default value is release - struct MAC_MainConfig__phr_Config *phr_config; - ///timer before triggering a periodic PHR - uint16_t periodicPHR_Timer; - ///timer before triggering a prohibit PHR - uint16_t prohibitPHR_Timer; - ///DL Pathloss change value - uint16_t PathlossChange; - ///number of subframe before triggering a periodic PHR - int16_t periodicPHR_SF; - ///number of subframe before triggering a prohibit PHR - int16_t prohibitPHR_SF; - ///DL Pathloss Change in db - uint16_t PathlossChange_db; - - /// default value is false - uint16_t extendedBSR_Sizes_r10; - /// default value is false - uint16_t extendedPHR_r10; - - //Bj bucket usage per lcid - int16_t Bj[MAX_NUM_LCID]; - // Bucket size per lcid - int16_t bucket_size[MAX_NUM_LCID]; + /// buffer status for each lcgid + uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology + /// keep the number of bytes in rlc buffer for each lcgid + int32_t BSR_bytes[MAX_NUM_LCGID]; + /// after multiplexing buffer remain for each lcid + int32_t LCID_buffer_remain[MAX_NUM_LCID]; + /// sum of all lcid buffer size + uint16_t All_lcid_buffer_size_lastTTI; + /// buffer status for each lcid + uint8_t LCID_status[MAX_NUM_LCID]; + /// SR pending as defined in 36.321 + uint8_t SR_pending; + /// SR_COUNTER as defined in 36.321 + uint16_t SR_COUNTER; + /// logical channel group ide for each LCID + uint8_t LCGID[MAX_NUM_LCID]; + /// retxBSR-Timer, default value is sf2560 + uint16_t retxBSR_Timer; + /// retxBSR_SF, number of subframe before triggering a regular BSR + uint16_t retxBSR_SF; + /// periodicBSR-Timer, default to infinity + uint16_t periodicBSR_Timer; + /// periodicBSR_SF, number of subframe before triggering a periodic BSR + uint16_t periodicBSR_SF; + /// default value is 0: not configured + uint16_t sr_ProhibitTimer; + /// sr ProhibitTime running + uint8_t sr_ProhibitTimer_Running; + /// default value to n5 + uint16_t maxHARQ_Tx; + /// default value is false + uint16_t ttiBundling; + /// default value is release + struct DRX_Config *drx_config; + /// default value is release + struct MAC_MainConfig__phr_Config *phr_config; + ///timer before triggering a periodic PHR + uint16_t periodicPHR_Timer; + ///timer before triggering a prohibit PHR + uint16_t prohibitPHR_Timer; + ///DL Pathloss change value + uint16_t PathlossChange; + ///number of subframe before triggering a periodic PHR + int16_t periodicPHR_SF; + ///number of subframe before triggering a prohibit PHR + int16_t prohibitPHR_SF; + ///DL Pathloss Change in db + uint16_t PathlossChange_db; + + /// default value is false + uint16_t extendedBSR_Sizes_r10; + /// default value is false + uint16_t extendedPHR_r10; + + //Bj bucket usage per lcid + int16_t Bj[MAX_NUM_LCID]; + // Bucket size per lcid + int16_t bucket_size[MAX_NUM_LCID]; } UE_SCHEDULING_INFO; /*!\brief Top level UE MAC structure */ typedef struct { - uint16_t Node_id; - /// RX frame counter - frame_t rxFrame; - /// RX subframe counter - sub_frame_t rxSubframe; - /// TX frame counter - frame_t txFrame; - /// TX subframe counter - sub_frame_t txSubframe; - /// C-RNTI of UE - uint16_t crnti; - /// C-RNTI of UE before HO - rnti_t crnti_before_ho; ///user id (rnti) of connected UEs - /// uplink active flag - uint8_t ul_active; - /// pointer to RRC PHY configuration - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; - /// pointer to RACH_ConfigDedicated (NULL when not active, i.e. upon HO completion or T304 expiry) - struct RACH_ConfigDedicated *rach_ConfigDedicated; - /// pointer to RRC PHY configuration - struct PhysicalConfigDedicated *physicalConfigDedicated; + uint16_t Node_id; + /// RX frame counter + frame_t rxFrame; + /// RX subframe counter + sub_frame_t rxSubframe; + /// TX frame counter + frame_t txFrame; + /// TX subframe counter + sub_frame_t txSubframe; + /// C-RNTI of UE + uint16_t crnti; + /// C-RNTI of UE before HO + rnti_t crnti_before_ho; ///user id (rnti) of connected UEs + /// uplink active flag + uint8_t ul_active; + /// pointer to RRC PHY configuration + RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; + /// pointer to RACH_ConfigDedicated (NULL when not active, i.e. upon HO completion or T304 expiry) + struct RACH_ConfigDedicated *rach_ConfigDedicated; + /// pointer to RRC PHY configuration + struct PhysicalConfigDedicated *physicalConfigDedicated; #if defined(Rel10) || defined(Rel14) - /// pointer to RRC PHY configuration SCEll - struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10; + /// pointer to RRC PHY configuration SCEll + struct PhysicalConfigDedicatedSCell_r10 + *physicalConfigDedicatedSCell_r10; #endif - /// pointer to TDD Configuration (NULL for FDD) - TDD_Config_t *tdd_Config; - /// Number of adjacent cells to measure - uint8_t n_adj_cells; - /// Array of adjacent physical cell ids - uint32_t adj_cell_id[6]; - /// Pointer to RRC MAC configuration - MAC_MainConfig_t *macConfig; - /// Pointer to RRC Measurement gap configuration - MeasGapConfig_t *measGapConfig; - /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive. - LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID]; - /// Scheduling Information - UE_SCHEDULING_INFO scheduling_info; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Incoming DLSCH pdu for PHY - DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2]; - /// number of attempt for rach - uint8_t RA_attempt_number; - /// Random-access procedure flag - uint8_t RA_active; - /// Random-access window counter - int8_t RA_window_cnt; - /// Random-access Msg3 size in bytes - uint8_t RA_Msg3_size; - /// Random-access prachMaskIndex - uint8_t RA_prachMaskIndex; - /// Flag indicating Preamble set (A,B) used for first Msg3 transmission - uint8_t RA_usedGroupA; - /// Random-access Resources - PRACH_RESOURCES_t RA_prach_resources; - /// Random-access PREAMBLE_TRANSMISSION_COUNTER - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; - /// Random-access backoff counter - int16_t RA_backoff_cnt; - /// Random-access variable for window calculation (frame of last change in window counter) - uint32_t RA_tx_frame; - /// Random-access variable for window calculation (subframe of last change in window counter) - uint8_t RA_tx_subframe; - /// Random-access Group B maximum path-loss - /// Random-access variable for backoff (frame of last change in backoff counter) - uint32_t RA_backoff_frame; - /// Random-access variable for backoff (subframe of last change in backoff counter) - uint8_t RA_backoff_subframe; - /// Random-access Group B maximum path-loss - uint16_t RA_maxPL; - /// Random-access Contention Resolution Timer active flag - uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; - /// power headroom reporitng reconfigured - uint8_t PHR_reconfigured; - /// power headroom state as configured by the higher layers - uint8_t PHR_state; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t PHR_reporting_active; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t power_backoff_db[NUMBER_OF_eNB_MAX]; - /// BSR report falg management - uint8_t BSR_reporting_active; - /// retxBSR-Timer expires flag - uint8_t retxBSRTimer_expires_flag; - /// periodBSR-Timer expires flag - uint8_t periodBSRTimer_expires_flag; - - /// MBSFN_Subframe Configuration - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; + /// pointer to TDD Configuration (NULL for FDD) + TDD_Config_t *tdd_Config; + /// Number of adjacent cells to measure + uint8_t n_adj_cells; + /// Array of adjacent physical cell ids + uint32_t adj_cell_id[6]; + /// Pointer to RRC MAC configuration + MAC_MainConfig_t *macConfig; + /// Pointer to RRC Measurement gap configuration + MeasGapConfig_t *measGapConfig; + /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive. + LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID]; + /// Scheduling Information + UE_SCHEDULING_INFO scheduling_info; + /// Outgoing CCCH pdu for PHY + CCCH_PDU CCCH_pdu; + /// Outgoing RAR pdu for PHY + RAR_PDU RAR_pdu; + /// Incoming DLSCH pdu for PHY + DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2]; + /// number of attempt for rach + uint8_t RA_attempt_number; + /// Random-access procedure flag + uint8_t RA_active; + /// Random-access window counter + int8_t RA_window_cnt; + /// Random-access Msg3 size in bytes + uint8_t RA_Msg3_size; + /// Random-access prachMaskIndex + uint8_t RA_prachMaskIndex; + /// Flag indicating Preamble set (A,B) used for first Msg3 transmission + uint8_t RA_usedGroupA; + /// Random-access Resources + PRACH_RESOURCES_t RA_prach_resources; + /// Random-access PREAMBLE_TRANSMISSION_COUNTER + uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; + /// Random-access backoff counter + int16_t RA_backoff_cnt; + /// Random-access variable for window calculation (frame of last change in window counter) + uint32_t RA_tx_frame; + /// Random-access variable for window calculation (subframe of last change in window counter) + uint8_t RA_tx_subframe; + /// Random-access Group B maximum path-loss + /// Random-access variable for backoff (frame of last change in backoff counter) + uint32_t RA_backoff_frame; + /// Random-access variable for backoff (subframe of last change in backoff counter) + uint8_t RA_backoff_subframe; + /// Random-access Group B maximum path-loss + uint16_t RA_maxPL; + /// Random-access Contention Resolution Timer active flag + uint8_t RA_contention_resolution_timer_active; + /// Random-access Contention Resolution Timer count value + uint8_t RA_contention_resolution_cnt; + /// power headroom reporitng reconfigured + uint8_t PHR_reconfigured; + /// power headroom state as configured by the higher layers + uint8_t PHR_state; + /// power backoff due to power management (as allowed by P-MPRc) for this cell + uint8_t PHR_reporting_active; + /// power backoff due to power management (as allowed by P-MPRc) for this cell + uint8_t power_backoff_db[NUMBER_OF_eNB_MAX]; + /// BSR report falg management + uint8_t BSR_reporting_active; + /// retxBSR-Timer expires flag + uint8_t retxBSRTimer_expires_flag; + /// periodBSR-Timer expires flag + uint8_t periodBSRTimer_expires_flag; + + /// MBSFN_Subframe Configuration + struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? + /// number of subframe allocation pattern available for MBSFN sync area + uint8_t num_sf_allocation_pattern; #if defined(Rel10) || defined(Rel14) - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MCCH status - uint8_t mcch_status; - /// MSI status - uint8_t msi_status;// could be an array if there are >1 MCH in one MBSFN area + /// number of active MBSFN area + uint8_t num_active_mbsfn_area; + /// MBSFN Area Info + struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; + /// PMCH Config + struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; + /// MCCH status + uint8_t mcch_status; + /// MSI status + uint8_t msi_status; // could be an array if there are >1 MCH in one MBSFN area #endif - //#ifdef CBA - /// CBA RNTI for each group - uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; - /// last SFN for CBA channel access - uint8_t cba_last_access[NUM_MAX_CBA_GROUP]; - //#endif - /// total UE scheduler processing time - time_stats_t ue_scheduler; // total - /// UE ULSCH tx processing time inlcuding RLC interface (rlc_data_req) and mac header generation - time_stats_t tx_ulsch_sdu; - /// UE DLSCH rx processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser - time_stats_t rx_dlsch_sdu ; - /// UE query for MCH subframe processing time - time_stats_t ue_query_mch; - /// UE MCH rx processing time - time_stats_t rx_mch_sdu; - /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_si; - /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_p; + //#ifdef CBA + /// CBA RNTI for each group + uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; + /// last SFN for CBA channel access + uint8_t cba_last_access[NUM_MAX_CBA_GROUP]; + //#endif + /// total UE scheduler processing time + time_stats_t ue_scheduler; // total + /// UE ULSCH tx processing time inlcuding RLC interface (rlc_data_req) and mac header generation + time_stats_t tx_ulsch_sdu; + /// UE DLSCH rx processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser + time_stats_t rx_dlsch_sdu; + /// UE query for MCH subframe processing time + time_stats_t ue_query_mch; + /// UE MCH rx processing time + time_stats_t rx_mch_sdu; + /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind) + time_stats_t rx_si; + /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind) + time_stats_t rx_p; } UE_MAC_INST; /*! \brief ID of the neighboring cells used for HO*/ typedef struct { - uint16_t cell_ids[6]; - uint8_t n_adj_cells; + uint16_t cell_ids[6]; + uint8_t n_adj_cells; } neigh_cell_id_t; #include "proto.h" /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ - - - diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 6bcbc131068dddd4279f803880be89c34f1190ae..f7c3f5829d6b9005d632dcc9b5866011b86c1ed0 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -60,7 +60,7 @@ #endif #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #define ENABLE_MAC_PAYLOAD_DEBUG @@ -68,481 +68,693 @@ extern RAN_CONTEXT_t RC; -uint16_t pdcch_order_table[6] = {31,31,511,2047,2047,8191}; +uint16_t pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -void schedule_SRS(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP) +void +schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - nfapi_ul_config_request_body_t *ul_req; - int CC_id,UE_id; - COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; - SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon; - struct SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated; - uint8_t TSFC; - uint16_t deltaTSFC; // bitmap - uint8_t srs_SubframeConfig; - - // table for TSFC (Period) and deltaSFC (offset) - const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD - const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD - - uint16_t srsPeriodicity,srsOffset; - - for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) { - soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon; - // check if SRS is enabled in this frame/subframe - if (soundingRS_UL_ConfigCommon) { - srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; - if (cc[CC_id].tdd_Config == NULL) { // FDD - deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0]; - TSFC = deltaTSFCTabType1[srs_SubframeConfig][1]; - } - else { // TDD - deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0]; - TSFC = deltaTSFCTabType2[srs_SubframeConfig][1]; - } - // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC - uint16_t tmp = (subframeP % TSFC); - - if((1<<tmp) & deltaTSFC) { - // This is an SRS subframe, loop over UEs - for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue; - ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body; - - - // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet - if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue; - - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id); - - if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) { - if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) { - get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, &srsPeriodicity, &srsOffset); - if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) { - // Prorgram SRS - ul_req->srs_present = 1; - nfapi_ul_config_request_pdu_t* ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_SRS_PDU_TYPE; - ul_config_pdu->pdu_size = 2+(uint8_t)(2+sizeof(nfapi_ul_config_srs_pdu)); - ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);; - ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; - ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth; - ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; - ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;; - ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb; - ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex; - ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift; - // ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port = ;// - // ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs = ;// - RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP<<4)+subframeP; - ul_req->number_of_pdus++; - } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) - } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) - } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) - } // for (UE_id ... - } // if((1<<tmp) & deltaTSFC) - - }// SRS config - } + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; + nfapi_ul_config_request_body_t *ul_req; + int CC_id, UE_id; + COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; + SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon; + struct SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated; + uint8_t TSFC; + uint16_t deltaTSFC; // bitmap + uint8_t srs_SubframeConfig; + + // table for TSFC (Period) and deltaSFC (offset) + const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD + const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD + + uint16_t srsPeriodicity, srsOffset; + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + soundingRS_UL_ConfigCommon = + &cc[CC_id].radioResourceConfigCommon-> + soundingRS_UL_ConfigCommon; + // check if SRS is enabled in this frame/subframe + if (soundingRS_UL_ConfigCommon) { + srs_SubframeConfig = + soundingRS_UL_ConfigCommon->choice.setup. + srs_SubframeConfig; + if (cc[CC_id].tdd_Config == NULL) { // FDD + deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0]; + TSFC = deltaTSFCTabType1[srs_SubframeConfig][1]; + } else { // TDD + deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0]; + TSFC = deltaTSFCTabType2[srs_SubframeConfig][1]; + } + // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC + uint16_t tmp = (subframeP % TSFC); + + if ((1 << tmp) & deltaTSFC) { + // This is an SRS subframe, loop over UEs + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (RC.mac[module_idP]->UE_list.active[UE_id] != TRUE) + continue; + ul_req = + &RC.mac[module_idP]->UL_req[CC_id]. + ul_config_request_body; + + + // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet + if (mac_eNB_get_rrc_status + (module_idP, + UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) + continue; + + AssertFatal(UE_list->UE_template[CC_id] + [UE_id].physicalConfigDedicated != NULL, + "physicalConfigDedicated is null for UE %d\n", + UE_id); + + if ((soundingRS_UL_ConfigDedicated = + UE_list->UE_template[CC_id] + [UE_id]. + physicalConfigDedicated->soundingRS_UL_ConfigDedicated) + != NULL) { + if (soundingRS_UL_ConfigDedicated->present == + SoundingRS_UL_ConfigDedicated_PR_setup) { + get_srs_pos(&cc[CC_id], + soundingRS_UL_ConfigDedicated->choice. + setup.srs_ConfigIndex, + &srsPeriodicity, &srsOffset); + if (((10 * frameP + + subframeP) % srsPeriodicity) == + srsOffset) { + // Prorgram SRS + ul_req->srs_present = 1; + nfapi_ul_config_request_pdu_t + * ul_config_pdu = + &ul_req-> + ul_config_pdu_list + [ul_req->number_of_pdus]; + memset((void *) ul_config_pdu, 0, + sizeof + (nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_SRS_PDU_TYPE; + ul_config_pdu->pdu_size = + 2 + (uint8_t) (2 + + sizeof + (nfapi_ul_config_srs_pdu)); + ul_config_pdu->srs_pdu.srs_pdu_rel8.size = + (uint8_t) + sizeof(nfapi_ul_config_srs_pdu);; + ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = + UE_list->UE_template[CC_id][UE_id]. + rnti; + ul_config_pdu->srs_pdu. + srs_pdu_rel8.srs_bandwidth = + soundingRS_UL_ConfigDedicated-> + choice.setup.srs_Bandwidth; + ul_config_pdu->srs_pdu. + srs_pdu_rel8.frequency_domain_position + = + soundingRS_UL_ConfigDedicated-> + choice.setup.freqDomainPosition; + ul_config_pdu->srs_pdu. + srs_pdu_rel8.srs_hopping_bandwidth = + soundingRS_UL_ConfigDedicated-> + choice.setup.srs_HoppingBandwidth;; + ul_config_pdu->srs_pdu. + srs_pdu_rel8.transmission_comb = + soundingRS_UL_ConfigDedicated-> + choice.setup.transmissionComb; + ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = + soundingRS_UL_ConfigDedicated-> + choice.setup.srs_ConfigIndex; + ul_config_pdu->srs_pdu. + srs_pdu_rel8.sounding_reference_cyclic_shift + = + soundingRS_UL_ConfigDedicated-> + choice.setup.cyclicShift; + // ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port = ;// + // ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs = ;// + RC.mac[module_idP]->UL_req[CC_id].sfn_sf = + (frameP << 4) + subframeP; + ul_req->number_of_pdus++; + } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) + } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) + } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) + } // for (UE_id ... + } // if((1<<tmp) & deltaTSFC) + + } // SRS config + } } -void schedule_CSI(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP) +void +schedule_CSI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - COMMON_channels_t *cc; - nfapi_ul_config_request_body_t *ul_req; - int CC_id,UE_id; - struct CQI_ReportPeriodic *cqi_ReportPeriodic; - uint16_t Npd,N_OFFSET_CQI; - int H; - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - cc = &eNB->common_channels[CC_id]; - for (UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body; - - // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet - if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue; - - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id); - - if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) { - if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic)!=NULL && - (cqi_ReportPeriodic->present!=CQI_ReportPeriodic_PR_release)) { - //Rel8 Periodic CQI/PMI/RI reporting - - get_csi_params(cc,cqi_ReportPeriodic,&Npd,&N_OFFSET_CQI,&H); - - if ((((frameP*10)+subframeP)%Npd) == N_OFFSET_CQI) { // CQI opportunity - UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id]=(((frameP*10)+subframeP)/Npd)%H; - // Program CQI - nfapi_ul_config_request_pdu_t* ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; - ul_config_pdu->pdu_size = 2+(uint8_t)(2+sizeof(nfapi_ul_config_uci_cqi_pdu)); - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], - CC_id, - cc, - get_tmode(module_idP,CC_id,UE_id), - cqi_ReportPeriodic); - ul_req->number_of_pdus++; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; + COMMON_channels_t *cc; + nfapi_ul_config_request_body_t *ul_req; + int CC_id, UE_id; + struct CQI_ReportPeriodic *cqi_ReportPeriodic; + uint16_t Npd, N_OFFSET_CQI; + int H; + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; + + ul_req = + &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body; + + // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet + if (mac_eNB_get_rrc_status + (module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) + continue; + + AssertFatal(UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated + != NULL, + "physicalConfigDedicated is null for UE %d\n", + UE_id); + + if (UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + cqi_ReportConfig) { + if ((cqi_ReportPeriodic = + UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + cqi_ReportConfig->cqi_ReportPeriodic) != NULL + && (cqi_ReportPeriodic->present != + CQI_ReportPeriodic_PR_release)) { + //Rel8 Periodic CQI/PMI/RI reporting + + get_csi_params(cc, cqi_ReportPeriodic, &Npd, + &N_OFFSET_CQI, &H); + + if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) { // CQI opportunity + UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id] = + (((frameP * 10) + subframeP) / Npd) % H; + // Program CQI + nfapi_ul_config_request_pdu_t *ul_config_pdu = + &ul_req->ul_config_pdu_list[ul_req-> + number_of_pdus]; + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; + ul_config_pdu->pdu_size = + 2 + (uint8_t) (2 + + sizeof + (nfapi_ul_config_uci_cqi_pdu)); + ul_config_pdu->uci_cqi_pdu. + ue_information.ue_information_rel8.rnti = + UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu. + cqi_information.cqi_information_rel8. + pucch_index = + cqi_ReportPeriodic->choice. + setup.cqi_PUCCH_ResourceIndex; + ul_config_pdu->uci_cqi_pdu. + cqi_information.cqi_information_rel8. + dl_cqi_pmi_size = + get_rel8_dl_cqi_pmi_size + (&UE_list->UE_sched_ctrl[UE_id], CC_id, cc, + get_tmode(module_idP, CC_id, UE_id), + cqi_ReportPeriodic); + ul_req->number_of_pdus++; #if defined(Rel10) || defined(Rel14) - // PUT rel10-13 UCI options here + // PUT rel10-13 UCI options here #endif - } - else if ((cqi_ReportPeriodic->choice.setup.ri_ConfigIndex) && - ((((frameP*10)+subframeP)%((H*Npd)<<(*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex/161)))== - N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex%161))) { // RI opportunity - // Program RI - nfapi_ul_config_request_pdu_t* ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; - ul_config_pdu->pdu_size = 2+(uint8_t)(2+sizeof(nfapi_ul_config_uci_cqi_pdu)); - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = (cc->p_eNB==2)?1:2; - RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP<<4)+subframeP; - ul_req->number_of_pdus++; - } - - } // if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) { - } // if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) - } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + } else + if ((cqi_ReportPeriodic->choice.setup. + ri_ConfigIndex) + && ((((frameP * 10) + subframeP) % ((H * Npd) << (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex / 161))) == N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex % 161))) { // RI opportunity + // Program RI + nfapi_ul_config_request_pdu_t *ul_config_pdu = + &ul_req->ul_config_pdu_list[ul_req-> + number_of_pdus]; + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; + ul_config_pdu->pdu_size = + 2 + (uint8_t) (2 + + sizeof + (nfapi_ul_config_uci_cqi_pdu)); + ul_config_pdu->uci_cqi_pdu. + ue_information.ue_information_rel8.rnti = + UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu. + cqi_information.cqi_information_rel8. + pucch_index = + cqi_ReportPeriodic->choice. + setup.cqi_PUCCH_ResourceIndex; + ul_config_pdu->uci_cqi_pdu. + cqi_information.cqi_information_rel8. + dl_cqi_pmi_size = (cc->p_eNB == 2) ? 1 : 2; + RC.mac[module_idP]->UL_req[CC_id].sfn_sf = + (frameP << 4) + subframeP; + ul_req->number_of_pdus++; + } + + } // if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) { + } // if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) + } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { } -void schedule_SR(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) +void +schedule_SR(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - nfapi_ul_config_request_body_t *ul_req; - int CC_id; - int UE_id; - SchedulingRequestConfig_t *SRconfig; - int skip_ue; - int is_harq; - nfapi_ul_config_sr_information sr; - int i; - - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP; - - for (UE_id = 0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue; - - ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body; - - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id); - - // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet - if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED) continue; - - if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) { - if (SRconfig->present == SchedulingRequestConfig_PR_setup) { - if (SRconfig->choice.setup.sr_ConfigIndex <= 4) { // 5 ms SR period - if ((subframeP%5) != SRconfig->choice.setup.sr_ConfigIndex) - continue; - } else if (SRconfig->choice.setup.sr_ConfigIndex <= 14) { // 10 ms SR period - if (subframeP!=(SRconfig->choice.setup.sr_ConfigIndex-5)) - continue; - } else if (SRconfig->choice.setup.sr_ConfigIndex <= 34) { // 20 ms SR period - if ((10*(frameP&1)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-15)) - continue; - } else if (SRconfig->choice.setup.sr_ConfigIndex <= 74) { // 40 ms SR period - if ((10*(frameP&3)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-35)) - continue; - } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period - if ((10*(frameP&7)+subframeP) != (SRconfig->choice.setup.sr_ConfigIndex-75)) - continue; - } - } // SRconfig->present == SchedulingRequestConfig_PR_setup) - } // SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) - - // if we get here there is some PUCCH1 reception to schedule for SR - - skip_ue=0; - is_harq = 0; - // check that there is no existing UL grant for ULSCH which overrides the SR - for (i = 0; i < ul_req->number_of_pdus; i++) { - if (((ul_req->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE)|| - (ul_req->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE)|| - (ul_req->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE)|| - (ul_req->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE))&& - (ul_req->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { - skip_ue=1; - break; - } - /* if there is already an HARQ pdu, convert to SR_HARQ */ - else if ((ul_req->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE)&& - (ul_req->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { - is_harq = 1; - break; - } - } - - // drop the allocation because ULSCH with handle it with BSR - if (skip_ue==1) continue; - - LOG_D(MAC,"Frame %d, Subframe %d : Scheduling SR for UE %d/%x\n",frameP,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].rnti); - - // check Rel10 or Rel8 SR + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; + nfapi_ul_config_request_body_t *ul_req; + int CC_id; + int UE_id; + SchedulingRequestConfig_t *SRconfig; + int skip_ue; + int is_harq; + nfapi_ul_config_sr_information sr; + int i; + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + RC.mac[module_idP]->UL_req[CC_id].sfn_sf = + (frameP << 4) + subframeP; + + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (RC.mac[module_idP]->UE_list.active[UE_id] != TRUE) + continue; + + ul_req = + &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body; + + AssertFatal(UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated + != NULL, + "physicalConfigDedicated is null for UE %d\n", + UE_id); + + // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet + if (mac_eNB_get_rrc_status + (module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) + continue; + + if ((SRconfig = + UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + schedulingRequestConfig) != NULL) { + if (SRconfig->present == SchedulingRequestConfig_PR_setup) { + if (SRconfig->choice.setup.sr_ConfigIndex <= 4) { // 5 ms SR period + if ((subframeP % 5) != + SRconfig->choice.setup.sr_ConfigIndex) + continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 14) { // 10 ms SR period + if (subframeP != + (SRconfig->choice.setup.sr_ConfigIndex - 5)) + continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 34) { // 20 ms SR period + if ((10 * (frameP & 1) + subframeP) != + (SRconfig->choice.setup.sr_ConfigIndex - 15)) + continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 74) { // 40 ms SR period + if ((10 * (frameP & 3) + subframeP) != + (SRconfig->choice.setup.sr_ConfigIndex - 35)) + continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period + if ((10 * (frameP & 7) + subframeP) != + (SRconfig->choice.setup.sr_ConfigIndex - 75)) + continue; + } + } // SRconfig->present == SchedulingRequestConfig_PR_setup) + } // SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) + + // if we get here there is some PUCCH1 reception to schedule for SR + + skip_ue = 0; + is_harq = 0; + // check that there is no existing UL grant for ULSCH which overrides the SR + for (i = 0; i < ul_req->number_of_pdus; i++) { + if (((ul_req->ul_config_pdu_list[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) + || (ul_req->ul_config_pdu_list[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) + || (ul_req->ul_config_pdu_list[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) + || (ul_req->ul_config_pdu_list[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)) + && (ul_req->ul_config_pdu_list[i]. + ulsch_pdu.ulsch_pdu_rel8.rnti == + UE_list->UE_template[CC_id][UE_id].rnti)) { + skip_ue = 1; + break; + } + /* if there is already an HARQ pdu, convert to SR_HARQ */ + else if ((ul_req->ul_config_pdu_list[i].pdu_type == + NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) + && (ul_req->ul_config_pdu_list[i]. + uci_harq_pdu.ue_information. + ue_information_rel8.rnti == + UE_list->UE_template[CC_id][UE_id].rnti)) { + is_harq = 1; + break; + } + } + + // drop the allocation because ULSCH with handle it with BSR + if (skip_ue == 1) + continue; + + LOG_D(MAC, + "Frame %d, Subframe %d : Scheduling SR for UE %d/%x\n", + frameP, subframeP, UE_id, + UE_list->UE_template[CC_id][UE_id].rnti); + + // check Rel10 or Rel8 SR #if defined(Rel10) || defined(Rel14) - if ((UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) && - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)&& - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) { - sr.sr_information_rel10.number_of_pucch_resources = 1; - sr.sr_information_rel10.pucch_index_p1 = *UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; - } else + if ((UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) + && (UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + ext2->schedulingRequestConfig_v1020) + && (UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + ext2->schedulingRequestConfig_v1020)) { + sr.sr_information_rel10.number_of_pucch_resources = 1; + sr.sr_information_rel10.pucch_index_p1 = + *UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + ext2-> + schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; + } else #endif - { - sr.sr_information_rel8.pucch_index = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; - } - - /* if there is already an HARQ pdu, convert to SR_HARQ */ - if (is_harq) { - nfapi_ul_config_harq_information h = ul_req->ul_config_pdu_list[i].uci_harq_pdu.harq_information; - ul_req->ul_config_pdu_list[i].pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE; - ul_req->ul_config_pdu_list[i].uci_sr_harq_pdu.sr_information = sr; - ul_req->ul_config_pdu_list[i].uci_sr_harq_pdu.harq_information = h; - } else { - ul_req->ul_config_pdu_list[ul_req->number_of_pdus].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE; - ul_req->ul_config_pdu_list[ul_req->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; - ul_req->ul_config_pdu_list[ul_req->number_of_pdus].uci_sr_pdu.sr_information = sr; - ul_req->number_of_pdus++; - } /* if (is_harq) */ - } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) - } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) + { + sr.sr_information_rel8.pucch_index = + UE_list-> + UE_template[CC_id][UE_id].physicalConfigDedicated-> + schedulingRequestConfig->choice.setup. + sr_PUCCH_ResourceIndex; + } + + /* if there is already an HARQ pdu, convert to SR_HARQ */ + if (is_harq) { + nfapi_ul_config_harq_information h = + ul_req->ul_config_pdu_list[i].uci_harq_pdu. + harq_information; + ul_req->ul_config_pdu_list[i].pdu_type = + NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE; + ul_req->ul_config_pdu_list[i].uci_sr_harq_pdu. + sr_information = sr; + ul_req->ul_config_pdu_list[i].uci_sr_harq_pdu. + harq_information = h; + } else { + ul_req->ul_config_pdu_list[ul_req->number_of_pdus]. + pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE; + ul_req->ul_config_pdu_list[ul_req-> + number_of_pdus].uci_sr_pdu. + ue_information.ue_information_rel8.rnti = + UE_list->UE_template[CC_id][UE_id].rnti; + ul_req->ul_config_pdu_list[ul_req-> + number_of_pdus].uci_sr_pdu. + sr_information = sr; + ul_req->number_of_pdus++; + } /* if (is_harq) */ + } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) + } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) } -void check_ul_failure(module_id_t module_idP,int CC_id,int UE_id, - frame_t frameP, sub_frame_t subframeP) +void +check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, + frame_t frameP, sub_frame_t subframeP) { - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; - uint16_t rnti = UE_RNTI(module_idP,UE_id); - COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; - - // check uplink failure - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer>0)&& - (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync==0)) { - LOG_I(MAC,"UE %d rnti %x: UL Failure timer %d \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent==0) { - UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=1; - - // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe) - nfapi_dl_config_request_pdu_t* dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format1A); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >=0) && (cc[CC_id].mib->message.dl_Bandwidth<6), - "illegal dl_Bandwidth %d\n",(int)cc[CC_id].mib->message.dl_Bandwidth); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth]; - DL_req[CC_id].dl_config_request_body.number_dci++; - DL_req[CC_id].dl_config_request_body.number_pdu++; - LOG_I(MAC,"UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding); - } - else { // ra_pdcch_sent==1 - LOG_I(MAC,"UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0) - UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=0; // resend every 4 frames - } - - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; - // check threshold - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) { - // inform RRC of failure and clear timer - LOG_I(MAC,"UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti); - mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti); - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0; - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1; - } - } // ul_failure_timer>0 + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; + uint16_t rnti = UE_RNTI(module_idP, UE_id); + COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; + + // check uplink failure + if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && + (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { + LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti, + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { + UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; + + // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe) + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &DL_req[CC_id]. + dl_config_request_body.dl_config_pdu_list[DL_req[CC_id]. + dl_config_request_body.number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = + NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, CC_id), + UE_list->UE_sched_ctrl[UE_id]. + dl_cqi[CC_id], format1A); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >= 0) + && (cc[CC_id].mib->message.dl_Bandwidth < 6), + "illegal dl_Bandwidth %d\n", + (int) cc[CC_id].mib->message.dl_Bandwidth); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + resource_block_coding = + pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth]; + DL_req[CC_id].dl_config_request_body.number_dci++; + DL_req[CC_id].dl_config_request_body.number_pdu++; + LOG_I(MAC, + "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n", + UE_id, rnti, + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_block_coding); + } else { // ra_pdcch_sent==1 + LOG_I(MAC, + "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n", + UE_id, rnti, + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0) + UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 4 frames + } + + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; + // check threshold + if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) { + // inform RRC of failure and clear timer + LOG_I(MAC, + "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n", + UE_id, rnti); + mac_eNB_rrc_ul_failure(module_idP, CC_id, frameP, subframeP, + rnti); + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; + } + } // ul_failure_timer>0 } -void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP) +void +clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP, + frame_t frameP, sub_frame_t subframeP) { - nfapi_dl_config_request_t *DL_req = &eNB->DL_req[0]; - nfapi_ul_config_request_t *UL_req = &eNB->UL_req[0]; - nfapi_hi_dci0_request_t *HI_DCI0_req = &eNB->HI_DCI0_req[0]; - nfapi_tx_request_t *TX_req = &eNB->TX_req[0]; + nfapi_dl_config_request_t *DL_req = &eNB->DL_req[0]; + nfapi_ul_config_request_t *UL_req = &eNB->UL_req[0]; + nfapi_hi_dci0_request_t *HI_DCI0_req = &eNB->HI_DCI0_req[0]; + nfapi_tx_request_t *TX_req = &eNB->TX_req[0]; - eNB->pdu_index[CC_idP] = 0; - DL_req[CC_idP].dl_config_request_body.number_pdcch_ofdm_symbols = 1; - DL_req[CC_idP].dl_config_request_body.number_dci = 0; - DL_req[CC_idP].dl_config_request_body.number_pdu = 0; - DL_req[CC_idP].dl_config_request_body.number_pdsch_rnti = 0; - DL_req[CC_idP].dl_config_request_body.transmission_power_pcfich = 6000; + eNB->pdu_index[CC_idP] = 0; + DL_req[CC_idP].dl_config_request_body.number_pdcch_ofdm_symbols = 1; + DL_req[CC_idP].dl_config_request_body.number_dci = 0; + DL_req[CC_idP].dl_config_request_body.number_pdu = 0; + DL_req[CC_idP].dl_config_request_body.number_pdsch_rnti = 0; + DL_req[CC_idP].dl_config_request_body.transmission_power_pcfich = 6000; - HI_DCI0_req[CC_idP].hi_dci0_request_body.sfnsf = subframeP + (frameP<<4); - HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci = 0; + HI_DCI0_req[CC_idP].hi_dci0_request_body.sfnsf = + subframeP + (frameP << 4); + HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci = 0; - UL_req[CC_idP].ul_config_request_body.number_of_pdus = 0; - UL_req[CC_idP].ul_config_request_body.rach_prach_frequency_resources = 0; // ignored, handled by PHY for now - UL_req[CC_idP].ul_config_request_body.srs_present = 0; // ignored, handled by PHY for now + UL_req[CC_idP].ul_config_request_body.number_of_pdus = 0; + UL_req[CC_idP].ul_config_request_body.rach_prach_frequency_resources = 0; // ignored, handled by PHY for now + UL_req[CC_idP].ul_config_request_body.srs_present = 0; // ignored, handled by PHY for now - TX_req[CC_idP].tx_request_body.number_of_pdus = 0; + TX_req[CC_idP].tx_request_body.number_of_pdus = 0; } -void copy_ulreq(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP) +void +copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { - int CC_id; - eNB_MAC_INST *eNB; - nfapi_ul_config_request_body_t *ul_req_tmp; - nfapi_ul_config_request_body_t *ul_req; + int CC_id; + eNB_MAC_INST *eNB; + nfapi_ul_config_request_body_t *ul_req_tmp; + nfapi_ul_config_request_body_t *ul_req; - eNB = RC.mac[module_idP]; + eNB = RC.mac[module_idP]; - for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - ul_req_tmp = &eNB->UL_req_tmp[CC_id][subframeP].ul_config_request_body; - ul_req = &eNB->UL_req[CC_id].ul_config_request_body; + ul_req_tmp = + &eNB->UL_req_tmp[CC_id][subframeP].ul_config_request_body; + ul_req = &eNB->UL_req[CC_id].ul_config_request_body; - eNB->UL_req[CC_id].sfn_sf = (frameP<<4) + subframeP; - ul_req->number_of_pdus = ul_req_tmp->number_of_pdus; - ul_req_tmp->number_of_pdus = 0; + eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP; + ul_req->number_of_pdus = ul_req_tmp->number_of_pdus; + ul_req_tmp->number_of_pdus = 0; - memcpy((void*)ul_req->ul_config_pdu_list, - (void*)ul_req_tmp->ul_config_pdu_list, - ul_req->number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t)); + memcpy((void *) ul_req->ul_config_pdu_list, + (void *) ul_req_tmp->ul_config_pdu_list, + ul_req->number_of_pdus * + sizeof(nfapi_ul_config_request_pdu_t)); - } + } } -void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) +void +eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP) { - int mbsfn_status[MAX_NUM_CCs]; - protocol_ctxt_t ctxt; + int mbsfn_status[MAX_NUM_CCs]; + protocol_ctxt_t ctxt; - int CC_id,i; //,next_i; - UE_list_t *UE_list=&RC.mac[module_idP]->UE_list; - rnti_t rnti; + int CC_id, i; //,next_i; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + rnti_t rnti; - COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; + COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; #if defined(FLEXRAN_AGENT_SB_IF) - Protocol__FlexranMessage *msg; + Protocol__FlexranMessage *msg; #endif - start_meas(&RC.mac[module_idP]->eNB_scheduler); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); + start_meas(&RC.mac[module_idP]->eNB_scheduler); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, + VCD_FUNCTION_IN); - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - mbsfn_status[CC_id]=0; + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + mbsfn_status[CC_id] = 0; - // clear vrb_maps - memset(cc[CC_id].vrb_map,0,100); - memset(cc[CC_id].vrb_map_UL,0,100); + // clear vrb_maps + memset(cc[CC_id].vrb_map, 0, 100); + memset(cc[CC_id].vrb_map_UL, 0, 100); #if defined(Rel10) || defined(Rel14) - cc[CC_id].mcch_active =0; + cc[CC_id].mcch_active = 0; #endif - RC.mac[module_idP]->frame = frameP; - RC.mac[module_idP]->subframe = subframeP; - - clear_nfapi_information(RC.mac[module_idP],CC_id,frameP,subframeP); - } - - // refresh UE list based on UEs dropped by PHY in previous subframe - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) continue; - - rnti = UE_RNTI(module_idP, i); - CC_id = UE_PCCID(module_idP, i); - - if ((frameP==0)&&(subframeP==0)) { - LOG_I(MAC,"UE rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", rnti, - UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync", - UE_list->UE_template[CC_id][i].phr_info, - UE_list->UE_sched_ctrl[i].dl_cqi[CC_id], - (UE_list->UE_sched_ctrl[i].pusch_snr[CC_id]-128)/2, - (UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id]-128)/2); - } + RC.mac[module_idP]->frame = frameP; + RC.mac[module_idP]->subframe = subframeP; - RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63; - if (i==UE_list->head) - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]); - // increment this, it is cleared when we receive an sdu - RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++; + clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, + subframeP); + } - RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++; - LOG_D(MAC,"UE %d/%x : ul_inactivity %d, cqi_req %d\n",i,rnti, - RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer, - RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer); - check_ul_failure(module_idP,CC_id,i,frameP,subframeP); + // refresh UE list based on UEs dropped by PHY in previous subframe + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) + continue; + + rnti = UE_RNTI(module_idP, i); + CC_id = UE_PCCID(module_idP, i); + + if ((frameP == 0) && (subframeP == 0)) { + LOG_I(MAC, + "UE rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", + rnti, + UE_list->UE_sched_ctrl[i].ul_out_of_sync == + 0 ? "in synch" : "out of sync", + UE_list->UE_template[CC_id][i].phr_info, + UE_list->UE_sched_ctrl[i].dl_cqi[CC_id], + (UE_list->UE_sched_ctrl[i].pusch_snr[CC_id] - 128) / 2, + (UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id] - 128) / 2); + } + + RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP * 10) + + subframeP] = -63; + if (i == UE_list->head) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME + (VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, + RC.eNB[module_idP][CC_id]-> + pusch_stats_bsr[i][(frameP * 10) + subframeP]); + // increment this, it is cleared when we receive an sdu + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++; + + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++; + LOG_D(MAC, "UE %d/%x : ul_inactivity %d, cqi_req %d\n", i, rnti, + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i]. + ul_inactivity_timer, + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer); + check_ul_failure(module_idP, CC_id, i, frameP, subframeP); - } + } - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP); - pdcp_run(&ctxt); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, + NOT_A_RNTI, frameP, subframeP, + module_idP); + pdcp_run(&ctxt); - rrc_rx_tx(&ctxt, - 0, // eNB index, unused in eNB - CC_id); + rrc_rx_tx(&ctxt, 0, // eNB index, unused in eNB + CC_id); #if defined(Rel10) || defined(Rel14) - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - if (cc[CC_id].MBMS_flag >0) { - start_meas(&RC.mac[module_idP]->schedule_mch); - mbsfn_status[CC_id] = schedule_MBMS(module_idP,CC_id,frameP,subframeP); - stop_meas(&RC.mac[module_idP]->schedule_mch); + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + if (cc[CC_id].MBMS_flag > 0) { + start_meas(&RC.mac[module_idP]->schedule_mch); + mbsfn_status[CC_id] = + schedule_MBMS(module_idP, CC_id, frameP, subframeP); + stop_meas(&RC.mac[module_idP]->schedule_mch); + } } - } #endif - // This schedules MIB - if ((subframeP==0) && (frameP&3) == 0) schedule_mib(module_idP,frameP,subframeP); - // This schedules SI for legacy LTE and eMTC starting in subframeP - schedule_SI(module_idP,frameP,subframeP); - // This schedules Random-Access for legacy LTE and eMTC starting in subframeP - schedule_RA(module_idP,frameP,subframeP); - // copy previously scheduled UL resources (ULSCH + HARQ) - copy_ulreq(module_idP,frameP,subframeP); - // This schedules SRS in subframeP - schedule_SRS(module_idP,frameP,subframeP); - // This schedules ULSCH in subframeP (dci0) - schedule_ulsch(module_idP,frameP,subframeP); - // This schedules UCI_SR in subframeP - schedule_SR(module_idP,frameP,subframeP); - // This schedules UCI_CSI in subframeP - schedule_CSI(module_idP, frameP, subframeP); - - // This schedules DLSCH in subframeP - schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); - - // Allocate CCEs for good after scheduling is done - - for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) allocate_CCEs(module_idP,CC_id,subframeP,0); - - - stop_meas(&RC.mac[module_idP]->eNB_scheduler); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); + // This schedules MIB + if ((subframeP == 0) && (frameP & 3) == 0) + schedule_mib(module_idP, frameP, subframeP); + // This schedules SI for legacy LTE and eMTC starting in subframeP + schedule_SI(module_idP, frameP, subframeP); + // This schedules Random-Access for legacy LTE and eMTC starting in subframeP + schedule_RA(module_idP, frameP, subframeP); + // copy previously scheduled UL resources (ULSCH + HARQ) + copy_ulreq(module_idP, frameP, subframeP); + // This schedules SRS in subframeP + schedule_SRS(module_idP, frameP, subframeP); + // This schedules ULSCH in subframeP (dci0) + schedule_ulsch(module_idP, frameP, subframeP); + // This schedules UCI_SR in subframeP + schedule_SR(module_idP, frameP, subframeP); + // This schedules UCI_CSI in subframeP + schedule_CSI(module_idP, frameP, subframeP); + + // This schedules DLSCH in subframeP + schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); + + // Allocate CCEs for good after scheduling is done + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + allocate_CCEs(module_idP, CC_id, subframeP, 0); + + + stop_meas(&RC.mac[module_idP]->eNB_scheduler); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, + VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index 9ddb78e01fe05033abbea3640ef1802a02d0cae4..327f5faafe16182cceb24ed5736661b47b0f186b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -29,6 +29,9 @@ */ +/* indented with: indent -kr eNB_scheduler_RA.c */ + + #include "assertions.h" #include "platform_types.h" #include "PHY/defs.h" @@ -55,1258 +58,1596 @@ #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus #include "T.h" -void add_msg3(module_id_t module_idP,int CC_id, RA_TEMPLATE *RA_template, frame_t frameP, sub_frame_t subframeP) { - - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - uint8_t j; - nfapi_ul_config_request_t *ul_req; - nfapi_ul_config_request_pdu_t *ul_config_pdu; - nfapi_ul_config_request_body_t *ul_req_body; - nfapi_hi_dci0_request_body_t *hi_dci0_req; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; +void +add_msg3(module_id_t module_idP, int CC_id, RA_t * ra, frame_t frameP, + sub_frame_t subframeP) +{ + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = &mac->common_channels[CC_id]; + uint8_t j; + nfapi_ul_config_request_t *ul_req; + nfapi_ul_config_request_pdu_t *ul_config_pdu; + nfapi_ul_config_request_body_t *ul_req_body; + nfapi_hi_dci0_request_body_t *hi_dci0_req; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; - uint8_t rvseq[4] = {0,2,3,1}; + uint8_t rvseq[4] = { 0, 2, 3, 1 }; - hi_dci0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; - ul_req = &eNB->UL_req_tmp[CC_id][RA_template->Msg3_subframe]; - ul_req_body = &ul_req->ul_config_request_body; - AssertFatal(RA_template->RA_active == TRUE,"RA is not active for RA %X\n",RA_template->rnti); + hi_dci0_req = &mac->HI_DCI0_req[CC_id].hi_dci0_request_body; + ul_req = &mac->UL_req_tmp[CC_id][ra->Msg3_subframe]; + ul_req_body = &ul_req->ul_config_request_body; + AssertFatal(ra->state != IDLE, "RA is not active for RA %X\n", + ra->rnti); #ifdef Rel14 - if (RA_template->rach_resource_type>0) { - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d CE level %d is active, Msg3 in (%d,%d)\n", - module_idP,frameP,subframeP,CC_id,RA_template->rach_resource_type-1, - RA_template->Msg3_frame,RA_template->Msg3_subframe); - LOG_D(MAC,"Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d)\n", - frameP,subframeP,RA_template->Msg3_frame,RA_template->Msg3_subframe,RA_template->msg3_nb_rb,RA_template->msg3_round); - - ul_config_pdu = &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus]; - - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_pdu)); - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = eNB->ul_handle++; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = RA_template->rnti; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = narrowband_to_first_rb(cc,RA_template->msg34_narrowband)+RA_template->msg3_first_rb; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = RA_template->msg3_nb_rb; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = rvseq[RA_template->msg3_round]; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = ((10*RA_template->Msg3_frame)+RA_template->Msg3_subframe)&7; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = 1; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = get_TBS_UL(RA_template->msg3_mcs, - RA_template->msg3_nb_rb); - // Re13 fields - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type = RA_template->rach_resource_type>2 ? 2 : 1; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions = 1; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number = 1; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io = (RA_template->Msg3_frame*10)+RA_template->Msg3_subframe; - ul_req_body->number_of_pdus++; - } // if (RA_template->rach_resource_type>0) { - else + if (ra->rach_resource_type > 0) { + LOG_D(MAC, + "[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d CE level %d is active, Msg3 in (%d,%d)\n", + module_idP, frameP, subframeP, CC_id, + ra->rach_resource_type - 1, ra->Msg3_frame, + ra->Msg3_subframe); + LOG_D(MAC, + "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d)\n", + frameP, subframeP, ra->Msg3_frame, ra->Msg3_subframe, + ra->msg3_nb_rb, ra->msg3_round); + + ul_config_pdu = + &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus]; + + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_pdu)); + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = mac->ul_handle++; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = ra->rnti; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = + narrowband_to_first_rb(cc, + ra->msg34_narrowband) + + ra->msg3_first_rb; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = + ra->msg3_nb_rb; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = + 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8. + frequency_hopping_enabled_flag = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = + rvseq[ra->msg3_round]; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = + ((10 * ra->Msg3_frame) + ra->Msg3_subframe) & 7; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = 1; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = + get_TBS_UL(ra->msg3_mcs, ra->msg3_nb_rb); + // Re13 fields + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type = + ra->rach_resource_type > 2 ? 2 : 1; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13. + total_number_of_repetitions = 1; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number = 1; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13. + initial_transmission_sf_io = + (ra->Msg3_frame * 10) + ra->Msg3_subframe; + ul_req_body->number_of_pdus++; + } // if (ra->rach_resource_type>0) { + else #endif { - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", - module_idP,frameP,subframeP,CC_id,RA_template->Msg3_frame,RA_template->Msg3_subframe); - - LOG_D(MAC,"Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", - frameP,subframeP,RA_template->Msg3_frame,RA_template->Msg3_subframe, - RA_template->msg3_nb_rb,RA_template->msg3_first_rb,RA_template->msg3_round); - - ul_config_pdu = &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus]; - - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_pdu)); - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = eNB->ul_handle++; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = RA_template->rnti; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = RA_template->msg3_first_rb; - AssertFatal(RA_template->msg3_nb_rb > 0, "nb_rb = 0\n"); - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = RA_template->msg3_nb_rb; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = rvseq[RA_template->msg3_round]; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = subframe2harqpid(cc,RA_template->Msg3_frame,RA_template->Msg3_subframe); - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = 0; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = 1; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = get_TBS_UL(10,RA_template->msg3_nb_rb); - ul_req_body->number_of_pdus++; - // save UL scheduling information for preprocessor - for (j=0;j<RA_template->msg3_nb_rb;j++) cc->vrb_map_UL[RA_template->msg3_first_rb+j]=1; - - - if (RA_template->msg3_round != 0) { // program HI too - hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi]; - memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_hi_pdu); - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = RA_template->msg3_first_rb; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; - hi_dci0_req->number_of_hi++; + LOG_D(MAC, + "[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", + module_idP, frameP, subframeP, CC_id, ra->Msg3_frame, + ra->Msg3_subframe); + + LOG_D(MAC, + "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", + frameP, subframeP, ra->Msg3_frame, ra->Msg3_subframe, + ra->msg3_nb_rb, ra->msg3_first_rb, ra->msg3_round); + + ul_config_pdu = + &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus]; + + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_pdu)); + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = mac->ul_handle++; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = ra->rnti; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = + ra->msg3_first_rb; + AssertFatal(ra->msg3_nb_rb > 0, "nb_rb = 0\n"); + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = + ra->msg3_nb_rb; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = + 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8. + frequency_hopping_enabled_flag = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = + rvseq[ra->msg3_round]; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = + subframe2harqpid(cc, ra->Msg3_frame, ra->Msg3_subframe); + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = 0; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = 1; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = + get_TBS_UL(10, ra->msg3_nb_rb); + ul_req_body->number_of_pdus++; // save UL scheduling information for preprocessor - for (j=0;j<RA_template->msg3_nb_rb;j++) cc->vrb_map_UL[RA_template->msg3_first_rb+j]=1; - - LOG_D(MAC,"[eNB %d][PUSCH-RA %x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) RA (mcs %d, first rb %d, nb_rb %d,round %d)\n", - module_idP,RA_template->rnti,CC_id,frameP,subframeP,10, - 1,1, - RA_template->msg3_round-1); - } // if (RA_template->msg3_round != 0) { // program HI too - } // non-BL/CE UE case + for (j = 0; j < ra->msg3_nb_rb; j++) + cc->vrb_map_UL[ra->msg3_first_rb + j] = 1; + + + if (ra->msg3_round != 0) { // program HI too + hi_dci0_pdu = + &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci + + hi_dci0_req->number_of_hi]; + memset((void *) hi_dci0_pdu, 0, + sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu); + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = + ra->msg3_first_rb; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; + hi_dci0_req->number_of_hi++; + // save UL scheduling information for preprocessor + for (j = 0; j < ra->msg3_nb_rb; j++) + cc->vrb_map_UL[ra->msg3_first_rb + j] = 1; + + LOG_D(MAC, + "[eNB %d][PUSCH-RA %x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) RA (mcs %d, first rb %d, nb_rb %d,round %d)\n", + module_idP, ra->rnti, CC_id, frameP, subframeP, 10, 1, 1, + ra->msg3_round - 1); + } // if (ra->msg3_round != 0) { // program HI too + } // non-BL/CE UE case } -void generate_Msg2(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template) { +void +generate_Msg2(module_id_t module_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, RA_t * ra) +{ + + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - - uint8_t *vrb_map; - int first_rb; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - nfapi_dl_config_request_body_t *dl_req; + uint8_t *vrb_map; + int first_rb; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; - vrb_map = cc[CC_idP].vrb_map; - dl_req = &eNB->DL_req[CC_idP].dl_config_request_body; - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); + vrb_map = cc[CC_idP].vrb_map; + dl_req = &mac->DL_req[CC_idP].dl_config_request_body; + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); #ifdef Rel14 - int rmax = 0; - int rep = 0; - int reps = 0; - int num_nb = 0; - - first_rb = 0; - struct PRACH_ConfigSIB_v1310 *ext4_prach; - PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; - PRACH_ParametersCE_r13_t *p[4]={NULL,NULL,NULL,NULL}; - - uint16_t absSF = (10*frameP)+subframeP; - uint16_t absSF_Msg2 = (10*RA_template->Msg2_frame)+RA_template->Msg2_subframe; - - if (absSF>absSF_Msg2) return; // we're not ready yet, need to be to start == - - if (cc[CC_idP].radioResourceConfigCommon_BR) { - - ext4_prach = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; - prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; - - switch (prach_ParametersListCE_r13->list.count) { - case 4: - p[3]=prach_ParametersListCE_r13->list.array[3]; - case 3: - p[2]=prach_ParametersListCE_r13->list.array[2]; - case 2: - p[1]=prach_ParametersListCE_r13->list.array[1]; - case 1: - p[0]=prach_ParametersListCE_r13->list.array[0]; - break; - default: - AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",(int)prach_ParametersListCE_r13->list.count); - break; - } - } - - if (RA_template->rach_resource_type > 0) { - - // This uses an MPDCCH Type 2 common allocation according to Section 9.1.5 36-213 - // Parameters: - // p=2+4 PRB set (number of PRB pairs 3) - // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 - // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates - // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates - // distributed transmission - - // rmax from SIB2 information - AssertFatal(rmax<9,"rmax>8!\n"); - rmax = 1<<p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13; - // choose r1 by default for RAR (Table 9.1.5-5) - rep = 0; - // get actual repetition count from Table 9.1.5-3 - reps = (rmax<=8)?(1<<rep):(rmax>>(3-rep)); - // get narrowband according to higher-layer config - num_nb = p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.count; - RA_template->msg2_narrowband = *p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.array[RA_template->preamble_index%num_nb]; - first_rb = narrowband_to_first_rb(&cc[CC_idP],RA_template->msg2_narrowband); - - if ((RA_template->msg2_mpdcch_repetition_cnt == 0) && - (mpdcch_sf_condition(eNB,CC_idP,frameP,subframeP,rmax,TYPE2,-1)>0)){ - // MPDCCH configuration for RAR - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming MPDCCH %d repetitions\n", - module_idP,frameP,subframeP,reps); - - - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu)); - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = (RA_template->rach_resource_type > 1) ? 11 : 10; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = RA_template->msg2_narrowband; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs = 6; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; // imposed (9.1.5 in 213) for Type 2 Common search space - AssertFatal(cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, - "cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = RA_template->RA_rnti; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = (RA_template->rach_resource_type < 3) ? 1 : 2; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = cc[CC_idP].physCellId; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io = (frameP*10)+subframeP; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(6,0,6); // Note: still to be checked if it should not be (getRIV(N_RB_DL,first_rb,6)) : Check nFAPI specifications and what is done L1 with this parameter - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of RAR, 208 bits with N1A_PRB=3 - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 1;// N1A_PRB=3 (36.212); => 208 bits for mcs=4, choose mcs according t message size TBD - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports = 1; - RA_template->msg2_mpdcch_repetition_cnt++; - dl_req->number_pdu++; - RA_template->Msg2_subframe = (RA_template->Msg2_subframe+9)%10; - - } //repetition_count==0 && SF condition met - if (RA_template->msg2_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, MPDCCH repetition %d\n", - module_idP,frameP,subframeP,RA_template->msg2_mpdcch_repetition_cnt); - - if (RA_template->msg2_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition - if (cc[CC_idP].tdd_Config==NULL) { // FDD case - // wait 2 subframes for PDSCH transmission - if (subframeP>7) RA_template->Msg2_frame = (frameP+1)&1023; - else RA_template->Msg2_frame = frameP; - RA_template->Msg2_subframe = (subframeP+2)%10; // +2 is the "n+x" from Section 7.1.11 in 36.213 + int rmax = 0; + int rep = 0; + int reps = 0; + int num_nb = 0; + + first_rb = 0; + struct PRACH_ConfigSIB_v1310 *ext4_prach; + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; + PRACH_ParametersCE_r13_t *p[4] = { NULL, NULL, NULL, NULL }; + + uint16_t absSF = (10 * frameP) + subframeP; + uint16_t absSF_Msg2 = (10 * ra->Msg2_frame) + ra->Msg2_subframe; + + if (absSF > absSF_Msg2) + return; // we're not ready yet, need to be to start == + + if (cc[CC_idP].radioResourceConfigCommon_BR) { + + ext4_prach = + cc[CC_idP].radioResourceConfigCommon_BR->ext4-> + prach_ConfigCommon_v1310; + prach_ParametersListCE_r13 = + &ext4_prach->prach_ParametersListCE_r13; + + switch (prach_ParametersListCE_r13->list.count) { + case 4: + p[3] = prach_ParametersListCE_r13->list.array[3]; + case 3: + p[2] = prach_ParametersListCE_r13->list.array[2]; + case 2: + p[1] = prach_ParametersListCE_r13->list.array[1]; + case 1: + p[0] = prach_ParametersListCE_r13->list.array[0]; + break; + default: + AssertFatal(1 == 0, + "Illegal count for prach_ParametersListCE_r13 %d\n", + (int) prach_ParametersListCE_r13->list.count); + break; } - else { - AssertFatal(1==0,"TDD case not done yet\n"); + } + + if (ra->rach_resource_type > 0) { + + // This uses an MPDCCH Type 2 common allocation according to Section 9.1.5 36-213 + // Parameters: + // p=2+4 PRB set (number of PRB pairs 3) + // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 + // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates + // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates + // distributed transmission + + // rmax from SIB2 information + AssertFatal(rmax < 9, "rmax>8!\n"); + rmax = + 1 << p[ra->rach_resource_type - + 1]->mpdcch_NumRepetition_RA_r13; + // choose r1 by default for RAR (Table 9.1.5-5) + rep = 0; + // get actual repetition count from Table 9.1.5-3 + reps = (rmax <= 8) ? (1 << rep) : (rmax >> (3 - rep)); + // get narrowband according to higher-layer config + num_nb = + p[ra->rach_resource_type - + 1]->mpdcch_NarrowbandsToMonitor_r13.list.count; + ra->msg2_narrowband = + *p[ra->rach_resource_type - + 1]->mpdcch_NarrowbandsToMonitor_r13.list.array[ra-> + preamble_index + % num_nb]; + first_rb = + narrowband_to_first_rb(&cc[CC_idP], ra->msg2_narrowband); + + if ((ra->msg2_mpdcch_repetition_cnt == 0) && + (mpdcch_sf_condition + (mac, CC_idP, frameP, subframeP, rmax, TYPE2, -1) > 0)) { + // MPDCCH configuration for RAR + LOG_D(MAC, + "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming MPDCCH %d repetitions\n", + module_idP, frameP, subframeP, reps); + + + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_mpdcch_pdu)); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = + (ra->rach_resource_type > 1) ? 11 : 10; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = + ra->msg2_narrowband; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + number_of_prb_pairs = 6; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; // imposed (9.1.5 in 213) for Type 2 Common search space + AssertFatal(cc[CC_idP]. + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 + != NULL, + "cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = + cc[CC_idP].sib1_v13ext-> + bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = ra->RA_rnti; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = + (ra->rach_resource_type < 3) ? 1 : 2; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + drms_scrambling_init = cc[CC_idP].physCellId; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + initial_transmission_sf_io = (frameP * 10) + subframeP; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(6, 0, 6); // Note: still to be checked if it should not be (getRIV(N_RB_DL,first_rb,6)) : Check nFAPI specifications and what is done L1 with this parameter + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of RAR, 208 bits with N1A_PRB=3 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + harq_resource_offset = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 1; // N1A_PRB=3 (36.212); => 208 bits for mcs=4, choose mcs according t message size TBD + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.downlink_assignment_index_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + downlink_assignment_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + allocate_prach_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag + = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag + = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + number_of_tx_antenna_ports = 1; + ra->msg2_mpdcch_repetition_cnt++; + dl_req->number_pdu++; + ra->Msg2_subframe = (ra->Msg2_subframe + 9) % 10; + + } //repetition_count==0 && SF condition met + if (ra->msg2_mpdcch_repetition_cnt > 0) { // we're in a stream of repetitions + LOG_D(MAC, + "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, MPDCCH repetition %d\n", + module_idP, frameP, subframeP, + ra->msg2_mpdcch_repetition_cnt); + + if (ra->msg2_mpdcch_repetition_cnt == reps) { // this is the last mpdcch repetition + if (cc[CC_idP].tdd_Config == NULL) { // FDD case + // wait 2 subframes for PDSCH transmission + if (subframeP > 7) + ra->Msg2_frame = (frameP + 1) & 1023; + else + ra->Msg2_frame = frameP; + ra->Msg2_subframe = (subframeP + 2) % 10; // +2 is the "n+x" from Section 7.1.11 in 36.213 + } else { + AssertFatal(1 == 0, "TDD case not done yet\n"); + } + } // mpdcch_repetition_count == reps + ra->msg2_mpdcch_repetition_cnt++; + + if ((ra->Msg2_frame == frameP) + && (ra->Msg2_subframe == subframeP)) { + // Program PDSCH + LOG_D(MAC, + "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming PDSCH\n", + module_idP, frameP, subframeP); + ra->state = WAITMSG3; + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + mac->pdu_index[CC_idP]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = ra->RA_rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + resource_allocation_type = 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + resource_block_coding = getRIV(N_RB_DL, first_rb, 6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = + 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + transmission_scheme = (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = + 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = + (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = + cc[CC_idP]. + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13-> + startSymbolBR_r13; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = + (ra->rach_resource_type < 3) ? 1 : 2;; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13. + initial_transmission_sf_io = (10 * frameP) + subframeP; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = + 0; + dl_req->number_pdu++; + + // Program UL processing for Msg3, same as regular LTE + get_Msg3alloc(&cc[CC_idP], subframeP, frameP, + &ra->Msg3_frame, &ra->Msg3_subframe); + add_msg3(module_idP, CC_idP, ra, frameP, subframeP); + fill_rar_br(mac, CC_idP, ra, frameP, subframeP, + cc[CC_idP].RAR_pdu.payload, + ra->rach_resource_type - 1); + // DL request + mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP; + TX_req = + &mac->TX_req[CC_idP].tx_request_body.tx_pdu_list[mac-> + TX_req + [CC_idP]. + tx_request_body.number_of_pdus]; + TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble + TX_req->pdu_index = mac->pdu_index[CC_idP]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 7; + TX_req->segments[0].segment_data = + cc[CC_idP].RAR_pdu.payload; + mac->TX_req[CC_idP].tx_request_body.number_of_pdus++; + } } - }// mpdcch_repetition_count == reps - RA_template->msg2_mpdcch_repetition_cnt++; - - if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) { - // Program PDSCH - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming PDSCH\n", - module_idP,frameP,subframeP); - RA_template->generate_rar = 0; - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_idP]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->RA_rnti; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - - // Rel10 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; - // Rel13 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = (RA_template->rach_resource_type < 3) ? 1 : 2;; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = (10*frameP)+subframeP; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = 0; - dl_req->number_pdu++; - - // Program UL processing for Msg3, same as regular LTE - get_Msg3alloc(&cc[CC_idP],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe); - add_msg3(module_idP,CC_idP, RA_template,frameP,subframeP); - fill_rar_br(eNB,CC_idP,RA_template,frameP,subframeP,cc[CC_idP].RAR_pdu.payload,RA_template->rach_resource_type-1); - // DL request - eNB->TX_req[CC_idP].sfn_sf = (frameP<<4)+subframeP; - TX_req = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; - TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble - TX_req->pdu_index = eNB->pdu_index[CC_idP]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = 7; - TX_req->segments[0].segment_data = cc[CC_idP].RAR_pdu.payload; - eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++; - } - } - - } - else + + } else #endif { - if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI, RA_active %d format 1A (%d,%d))\n", - module_idP, CC_idP, frameP, subframeP, - RA_template->RA_active, - - RA_template->RA_dci_fmt1, - RA_template->RA_dci_size_bits1); - - // Allocate 4 PRBS starting in RB 0 - first_rb = 0; - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->RA_rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); - - // This checks if the above DCI allocation is feasible in current subframe - if (!CCE_allocation_infeasible(module_idP,CC_idP,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->RA_rnti)) { - LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for RA_RNTI %x\n", - frameP,subframeP,RA_template->RA_rnti); - dl_req->number_dci++; - dl_req->number_pdu++; - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_idP]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->RA_rnti; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - dl_req->number_pdu++; - - // Program UL processing for Msg3 - get_Msg3alloc(&cc[CC_idP],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe); - - LOG_D(MAC,"Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", - frameP,subframeP,RA_template->Msg3_frame,RA_template->Msg3_subframe); - - fill_rar(module_idP,CC_idP,frameP,cc[CC_idP].RAR_pdu.payload,N_RB_DL,7); - add_msg3(module_idP,CC_idP, RA_template,frameP,subframeP); - - // DL request - eNB->TX_req[CC_idP].sfn_sf = (frameP<<4)+subframeP; - TX_req = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; - TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble - TX_req->pdu_index = eNB->pdu_index[CC_idP]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = 7; - TX_req->segments[0].segment_data = cc[CC_idP].RAR_pdu.payload; - eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++; - } // PDCCH CCE allocation is feasible - } // Msg2 frame/subframe condition - } // else BL/CE + if ((ra->Msg2_frame == frameP) && (ra->Msg2_subframe == subframeP)) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI, state %d\n", + module_idP, CC_idP, frameP, subframeP, ra->state); + + // Allocate 4 PRBS starting in RB 0 + first_rb = 0; + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = + NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = ra->RA_rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + new_data_indicator_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + redundancy_version_1 = 0; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + + // This checks if the above DCI allocation is feasible in current subframe + if (!CCE_allocation_infeasible + (module_idP, CC_idP, 0, subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, ra->RA_rnti)) { + LOG_D(MAC, + "Frame %d: Subframe %d : Adding common DCI for RA_RNTI %x\n", + frameP, subframeP, ra->RA_rnti); + dl_req->number_dci++; + dl_req->number_pdu++; + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + mac->pdu_index[CC_idP]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = ra->RA_rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = + 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + transmission_scheme = (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = + 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = + (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Program UL processing for Msg3 + get_Msg3alloc(&cc[CC_idP], subframeP, frameP, + &ra->Msg3_frame, &ra->Msg3_subframe); + + LOG_D(MAC, + "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", + frameP, subframeP, ra->Msg3_frame, + ra->Msg3_subframe); + + fill_rar(module_idP, CC_idP, ra, frameP, + cc[CC_idP].RAR_pdu.payload, N_RB_DL, 7); + add_msg3(module_idP, CC_idP, ra, frameP, subframeP); + ra->state = WAITMSG3; + + // DL request + mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP; + TX_req = + &mac->TX_req[CC_idP].tx_request_body.tx_pdu_list[mac-> + TX_req + [CC_idP]. + tx_request_body.number_of_pdus]; + TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble + TX_req->pdu_index = mac->pdu_index[CC_idP]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 7; + TX_req->segments[0].segment_data = + cc[CC_idP].RAR_pdu.payload; + mac->TX_req[CC_idP].tx_request_body.number_of_pdus++; + } // PDCCH CCE allocation is feasible + } // Msg2 frame/subframe condition + } // else BL/CE } -void generate_Msg4(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template){ +void +generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, RA_t * ra) +{ - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - int16_t rrc_sdu_length; - int UE_id = -1; - uint16_t msg4_padding; - uint16_t msg4_post_padding; - uint16_t msg4_header; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + int16_t rrc_sdu_length; + int UE_id = -1; + uint16_t msg4_padding; + uint16_t msg4_post_padding; + uint16_t msg4_header; - uint8_t *vrb_map; - int first_rb; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_ul_config_request_pdu_t *ul_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - UE_list_t *UE_list=&eNB->UE_list; - nfapi_dl_config_request_body_t *dl_req; - nfapi_ul_config_request_body_t *ul_req; - uint8_t lcid; - uint8_t offset; + uint8_t *vrb_map; + int first_rb; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_ul_config_request_pdu_t *ul_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + UE_list_t *UE_list = &mac->UE_list; + nfapi_dl_config_request_body_t *dl_req; + nfapi_ul_config_request_body_t *ul_req; + uint8_t lcid; + uint8_t offset; #ifdef Rel14 - int rmax = 0; - int rep = 0; - int reps = 0; - - - first_rb = 0; - struct PRACH_ConfigSIB_v1310 *ext4_prach; - struct PUCCH_ConfigCommon_v1310 *ext4_pucch; - PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; - struct N1PUCCH_AN_InfoList_r13 *pucch_N1PUCCH_AN_InfoList_r13; - PRACH_ParametersCE_r13_t *p[4]={NULL,NULL,NULL,NULL}; - int pucchreps[4]={1,1,1,1}; - int n1pucchan[4]={0,0,0,0}; - - if (cc[CC_idP].radioResourceConfigCommon_BR) { - - ext4_prach = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; - ext4_pucch = cc[CC_idP].radioResourceConfigCommon_BR->ext4->pucch_ConfigCommon_v1310; - prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; - pucch_N1PUCCH_AN_InfoList_r13 = ext4_pucch->n1PUCCH_AN_InfoList_r13; - AssertFatal(prach_ParametersListCE_r13!=NULL,"prach_ParametersListCE_r13 is null\n"); - AssertFatal(pucch_N1PUCCH_AN_InfoList_r13!=NULL,"pucch_N1PUCCH_AN_InfoList_r13 is null\n"); - // check to verify CE-Level compatibility in SIB2_BR - AssertFatal(prach_ParametersListCE_r13->list.count == pucch_N1PUCCH_AN_InfoList_r13->list.count, - "prach_ParametersListCE_r13->list.count!= pucch_N1PUCCH_AN_InfoList_r13->list.count\n"); - - switch (prach_ParametersListCE_r13->list.count) { - case 4: - p[3] = prach_ParametersListCE_r13->list.array[3]; - n1pucchan[3] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[3]; - AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level3_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level3 shouldn't be NULL\n"); - pucchreps[3] = (int)(4<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level3_r13); - - case 3: - p[2] = prach_ParametersListCE_r13->list.array[2]; - n1pucchan[2] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[2]; - AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level2 shouldn't be NULL\n"); - pucchreps[2] = (int)(4<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13); - case 2: - p[1] =prach_ParametersListCE_r13->list.array[1]; - n1pucchan[1] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[1]; - AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level1 shouldn't be NULL\n"); - pucchreps[1] = (int)(1<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level1_r13); - case 1: - p[0] = prach_ParametersListCE_r13->list.array[0]; - n1pucchan[0] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[0]; - AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level0 shouldn't be NULL\n"); - pucchreps[0] = (int)(1<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level0_r13); - default: - AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count); + int rmax = 0; + int rep = 0; + int reps = 0; + + + first_rb = 0; + struct PRACH_ConfigSIB_v1310 *ext4_prach; + struct PUCCH_ConfigCommon_v1310 *ext4_pucch; + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; + struct N1PUCCH_AN_InfoList_r13 *pucch_N1PUCCH_AN_InfoList_r13; + PRACH_ParametersCE_r13_t *p[4] = { NULL, NULL, NULL, NULL }; + int pucchreps[4] = { 1, 1, 1, 1 }; + int n1pucchan[4] = { 0, 0, 0, 0 }; + + if (cc[CC_idP].radioResourceConfigCommon_BR) { + + ext4_prach = + cc[CC_idP].radioResourceConfigCommon_BR->ext4-> + prach_ConfigCommon_v1310; + ext4_pucch = + cc[CC_idP].radioResourceConfigCommon_BR->ext4-> + pucch_ConfigCommon_v1310; + prach_ParametersListCE_r13 = + &ext4_prach->prach_ParametersListCE_r13; + pucch_N1PUCCH_AN_InfoList_r13 = + ext4_pucch->n1PUCCH_AN_InfoList_r13; + AssertFatal(prach_ParametersListCE_r13 != NULL, + "prach_ParametersListCE_r13 is null\n"); + AssertFatal(pucch_N1PUCCH_AN_InfoList_r13 != NULL, + "pucch_N1PUCCH_AN_InfoList_r13 is null\n"); + // check to verify CE-Level compatibility in SIB2_BR + AssertFatal(prach_ParametersListCE_r13->list.count == + pucch_N1PUCCH_AN_InfoList_r13->list.count, + "prach_ParametersListCE_r13->list.count!= pucch_N1PUCCH_AN_InfoList_r13->list.count\n"); + + switch (prach_ParametersListCE_r13->list.count) { + case 4: + p[3] = prach_ParametersListCE_r13->list.array[3]; + n1pucchan[3] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[3]; + AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level3_r13 + != NULL, + "pucch_NumRepetitionCE_Msg4_Level3 shouldn't be NULL\n"); + pucchreps[3] = + (int) (4 << *ext4_pucch-> + pucch_NumRepetitionCE_Msg4_Level3_r13); + + case 3: + p[2] = prach_ParametersListCE_r13->list.array[2]; + n1pucchan[2] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[2]; + AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13 + != NULL, + "pucch_NumRepetitionCE_Msg4_Level2 shouldn't be NULL\n"); + pucchreps[2] = + (int) (4 << *ext4_pucch-> + pucch_NumRepetitionCE_Msg4_Level2_r13); + case 2: + p[1] = prach_ParametersListCE_r13->list.array[1]; + n1pucchan[1] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[1]; + AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13 + != NULL, + "pucch_NumRepetitionCE_Msg4_Level1 shouldn't be NULL\n"); + pucchreps[1] = + (int) (1 << *ext4_pucch-> + pucch_NumRepetitionCE_Msg4_Level1_r13); + case 1: + p[0] = prach_ParametersListCE_r13->list.array[0]; + n1pucchan[0] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[0]; + AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13 + != NULL, + "pucch_NumRepetitionCE_Msg4_Level0 shouldn't be NULL\n"); + pucchreps[0] = + (int) (1 << *ext4_pucch-> + pucch_NumRepetitionCE_Msg4_Level0_r13); + default: + AssertFatal(1 == 0, + "Illegal count for prach_ParametersListCE_r13 %d\n", + prach_ParametersListCE_r13->list.count); + } } - } #endif - vrb_map = cc[CC_idP].vrb_map; - - dl_req = &eNB->DL_req[CC_idP].dl_config_request_body; - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); - - UE_id = find_UE_id(module_idP,RA_template->rnti); - AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); - - // set HARQ process round to 0 for this UE - - if (cc->tdd_Config) RA_template->harq_pid = ((frameP*10)+subframeP)%10; - else RA_template->harq_pid = ((frameP*10)+subframeP)&7; - - - // Get RRCConnectionSetup for Piggyback - rrc_sdu_length = mac_rrc_data_req(module_idP, - CC_idP, - frameP, - CCCH, - 1, // 1 transport block - &cc[CC_idP].CCCH_pdu.payload[0], - ENB_FLAG_YES, - module_idP, - 0); // not used in this case - - AssertFatal(rrc_sdu_length>0, - "[MAC][eNB Scheduler] CCCH not allocated\n"); - - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n", - module_idP, CC_idP, frameP, subframeP,UE_id, rrc_sdu_length); - - + vrb_map = cc[CC_idP].vrb_map; + + dl_req = &mac->DL_req[CC_idP].dl_config_request_body; + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); + + UE_id = find_UE_id(module_idP, ra->rnti); + AssertFatal(UE_id >= 0, "Can't find UE for t-crnti\n"); + + // set HARQ process round to 0 for this UE + + if (cc->tdd_Config) + ra->harq_pid = ((frameP * 10) + subframeP) % 10; + else + ra->harq_pid = ((frameP * 10) + subframeP) & 7; + + + // Get RRCConnectionSetup for Piggyback + rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1, // 1 transport block + &cc[CC_idP].CCCH_pdu.payload[0], ENB_FLAG_YES, module_idP, 0); // not used in this case + + AssertFatal(rrc_sdu_length > 0, + "[MAC][eNB Scheduler] CCCH not allocated\n"); + + + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n", + module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length); + + #ifdef Rel14 - if (RA_template->rach_resource_type>0) { - - // Generate DCI + repetitions first - // This uses an MPDCCH Type 2 allocation according to Section 9.1.5 36-213, Type2 common allocation according to Table 7.1-8 (36-213) - // Parameters: - // p=2+4 PRB set (number of PRB pairs 6) - // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 - // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates - // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates - // distributed transmission - - // rmax from SIB2 information - rmax = p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13; - AssertFatal(rmax>=4,"choose rmax>=4 for enough repeititions, or reduce rep to 1 or 2\n"); - - // choose r3 by default for Msg4 (this is ok from table 9.1.5-3 for rmax = >=4, if we choose rmax <4 it has to be less - rep = 2; - // get actual repetition count from Table 9.1.5-3 - reps = (rmax<=8)?(1<<rep):(rmax>>(3-rep)); - // get first narrowband - first_rb = narrowband_to_first_rb(&cc[CC_idP],RA_template->msg34_narrowband); - - if ((RA_template->msg4_mpdcch_repetition_cnt == 0) && - (mpdcch_sf_condition(eNB,CC_idP,frameP,subframeP,rmax,TYPE2,-1)>0)){ - // MPDCCH configuration for RAR - - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu)); - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = (RA_template->rach_resource_type > 1) ? 11 : 10; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = RA_template->msg34_narrowband; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs = 6; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; - AssertFatal(cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, - "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 0; // t-C-RNTI - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = RA_template->RA_rnti; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = (RA_template->rach_resource_type < 3) ? 1 : 2; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = cc[CC_idP].physCellId; /// Check this is still N_id_cell for type2 common - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io = (frameP*10)+subframeP; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(6,0,6);// check if not getRIV(N_RB_DL,first_rb,6); - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of Msg4, 208 bits with N1A_PRB=3 - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = RA_template->harq_pid; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 1;// N1A_PRB=3; => 208 bits - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = 0; - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in - dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports = 1; - RA_template->msg4_mpdcch_repetition_cnt++; - dl_req->number_pdu++; - - } //repetition_count==0 && SF condition met - else if (RA_template->msg4_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions - RA_template->msg4_mpdcch_repetition_cnt++; - if (RA_template->msg4_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition - if (cc[CC_idP].tdd_Config==NULL) { // FDD case - // wait 2 subframes for PDSCH transmission - if (subframeP>7) RA_template->Msg4_frame = (frameP+1)&1023; - else RA_template->Msg4_frame = frameP; - RA_template->Msg4_subframe = (subframeP+2)%10; - } - else { - AssertFatal(1==0,"TDD case not done yet\n"); - } - } // mpdcch_repetition_count == reps - if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { - - // Program PDSCH - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 BR with RRC Piggyback (ce_level %d RNTI %x)\n", - module_idP, CC_idP, frameP, subframeP,RA_template->rach_resource_type-1,RA_template->rnti); - - AssertFatal(1==0,"Msg4 generation not finished for BL/CE UE\n"); - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_idP]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->rnti; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); // check that this isn't getRIV(6,0,6) - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; - - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = (RA_template->rach_resource_type < 3) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = (10*frameP)+subframeP; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = 0; - dl_req->number_pdu++; - - RA_template->generate_Msg4=0; - RA_template->wait_ack_Msg4=1; - - lcid=0; - - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][RA_template->harq_pid] = 0; - msg4_header = 1+6+1; // CR header, CR CE, SDU header - - if ((RA_template->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { - msg4_padding = RA_template->msg4_TBsize - rrc_sdu_length - msg4_header; - msg4_post_padding = 0; - } else { - msg4_padding = 0; - msg4_post_padding = RA_template->msg4_TBsize - rrc_sdu_length - msg4_header -1; - } - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", - module_idP,CC_idP,frameP,subframeP,RA_template->msg4_TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); - DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return - // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] - offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], - 1, //num_sdus - (unsigned short*)&rrc_sdu_length, // - &lcid, // sdu_lcid - 255, // no drx - 31, // no timing advance - RA_template->cont_res_id, // contention res id - msg4_padding, // no padding - msg4_post_padding); - - memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], - &cc[CC_idP].CCCH_pdu.payload[0], - rrc_sdu_length); - - // DL request - eNB->TX_req[CC_idP].sfn_sf = (frameP<<4)+subframeP; - TX_req = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; - TX_req->pdu_length = rrc_sdu_length; - TX_req->pdu_index = eNB->pdu_index[CC_idP]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = rrc_sdu_length; - TX_req->segments[0].segment_data = eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]; - eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++; - - // Program ACK/NAK for Msg4 PDSCH - int absSF = (RA_template->Msg3_frame*10)+RA_template->Msg3_subframe; - // see Section 10.2 from 36.213 - int ackNAK_absSF = absSF + reps + 4; - AssertFatal(reps>2,"Have to handle programming of ACK when PDSCH repetitions is > 2\n"); - ul_req = &eNB->UL_req_tmp[CC_idP][ackNAK_absSF%10].ul_config_request_body; - ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_uci_harq_pdu)); - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0; // don't know how to use this - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti = RA_template->rnti; - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.ue_type = (RA_template->rach_resource_type < 3) ? 1 : 2; - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.empty_symbols = 0; - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.total_number_of_repetitions = pucchreps[RA_template->rach_resource_type-1]; - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.repetition_number = 0; - // Note need to keep sending this across reptitions!!!! Not really for PUCCH, to ask small-cell forum, we'll see for the other messages, maybe parameters change across repetitions and FAPI has to provide for that - if (cc[CC_idP].tdd_Config==NULL) { // FDD case - ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.n_pucch_1_0 = n1pucchan[RA_template->rach_resource_type-1]; - // NOTE: How to fill in the rest of the n_pucch_1_0 information 213 Section 10.1.2.1 in the general case - // = N_ECCE_q + Delta_ARO + n1pucchan[ce_level] - // higher in the MPDCCH configuration, N_ECCE_q is hard-coded to 0, and harq resource offset to 0 => - // Delta_ARO = 0 from Table 10.1.2.1-1 - ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.harq_size = 1; // 1-bit ACK/NAK - } - else { - AssertFatal(1==0,"PUCCH configuration for ACK/NAK not handled yet for TDD BL/CE case\n"); - } - ul_req->number_of_pdus++; - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP), - T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], RA_template->msg4_TBsize)); - - if (opt_enabled==1) { - trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], - rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), - eNB->frame, eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", - module_idP, CC_idP, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); - } - } // Msg4 frame/subframe - } // msg4_mpdcch_repetition_count - } // rach_resource_type > 0 - else -#endif - { // This is normal LTE case - if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n", - module_idP, CC_idP, frameP, subframeP,RA_template->rnti); - - /// Choose first 4 RBs for Msg4, should really check that these are free! - first_rb=0; - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - - // Compute MCS/TBS for 3 PRB (coded on 4 vrb) - msg4_header = 1+6+1; // CR header, CR CE, SDU header - - if ((rrc_sdu_length+msg4_header) <= 22) { - RA_template->msg4_mcs = 4; - RA_template->msg4_TBsize = 22; - } else if ((rrc_sdu_length+msg4_header) <= 28) { - RA_template->msg4_mcs = 5; - RA_template->msg4_TBsize = 28; - } else if ((rrc_sdu_length+msg4_header) <= 32) { - RA_template->msg4_mcs = 6; - RA_template->msg4_TBsize = 32; - } else if ((rrc_sdu_length+msg4_header) <= 41) { - RA_template->msg4_mcs = 7; - RA_template->msg4_TBsize = 41; - } else if ((rrc_sdu_length+msg4_header) <= 49) { - RA_template->msg4_mcs = 8; - RA_template->msg4_TBsize = 49; - } else if ((rrc_sdu_length+msg4_header) <= 57) { - RA_template->msg4_mcs = 9; - RA_template->msg4_TBsize = 57; - } + if (ra->rach_resource_type > 0) { + + // Generate DCI + repetitions first + // This uses an MPDCCH Type 2 allocation according to Section 9.1.5 36-213, Type2 common allocation according to Table 7.1-8 (36-213) + // Parameters: + // p=2+4 PRB set (number of PRB pairs 6) + // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 + // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates + // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates + // distributed transmission + + // rmax from SIB2 information + rmax = p[ra->rach_resource_type - 1]->mpdcch_NumRepetition_RA_r13; + AssertFatal(rmax >= 4, + "choose rmax>=4 for enough repeititions, or reduce rep to 1 or 2\n"); + + // choose r3 by default for Msg4 (this is ok from table 9.1.5-3 for rmax = >=4, if we choose rmax <4 it has to be less + rep = 2; + // get actual repetition count from Table 9.1.5-3 + reps = (rmax <= 8) ? (1 << rep) : (rmax >> (3 - rep)); + // get first narrowband + first_rb = + narrowband_to_first_rb(&cc[CC_idP], ra->msg34_narrowband); + + if ((ra->msg4_mpdcch_repetition_cnt == 0) && + (mpdcch_sf_condition + (mac, CC_idP, frameP, subframeP, rmax, TYPE2, -1) > 0)) { + // MPDCCH configuration for RAR + + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_mpdcch_pdu)); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = + (ra->rach_resource_type > 1) ? 11 : 10; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = + ra->msg34_narrowband; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + number_of_prb_pairs = 6; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + mpdcch_tansmission_type = 1; + AssertFatal(cc[CC_idP]. + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 + != NULL, + "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = + cc[CC_idP].sib1_v13ext-> + bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 0; // t-C-RNTI + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = ra->RA_rnti; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = + (ra->rach_resource_type < 3) ? 1 : 2; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = cc[CC_idP].physCellId; /// Check this is still N_id_cell for type2 common + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + initial_transmission_sf_io = (frameP * 10) + subframeP; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(6, 0, 6); // check if not getRIV(N_RB_DL,first_rb,6); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of Msg4, 208 bits with N1A_PRB=3 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = + ra->harq_pid; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + harq_resource_offset = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 1; // N1A_PRB=3; => 208 bits + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.downlink_assignment_index_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + downlink_assignment_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + allocate_prach_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag + = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; + dl_config_pdu->mpdcch_pdu. + mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag + = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = + 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13. + number_of_tx_antenna_ports = 1; + ra->msg4_mpdcch_repetition_cnt++; + dl_req->number_pdu++; - fill_nfapi_dl_dci_1A(dl_config_pdu, - 4, // aggregation_level - RA_template->rnti, // rnti - 1, // rnti_type, CRNTI - RA_template->harq_pid, // harq_process - 1, // tpc, none - getRIV(N_RB_DL,first_rb,4), // resource_block_coding - RA_template->msg4_mcs, // mcs - 1, // ndi - 0, // rv - 0); // vrb_flag - LOG_D(MAC,"Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n", - frameP, - subframeP, - dl_req->number_pdu, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process, - &dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding); - AssertFatal(dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding < 8192, - "resource_block_coding %u < 8192\n", - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding); - if (!CCE_allocation_infeasible(module_idP,CC_idP,1, - subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - RA_template->rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - - RA_template->generate_Msg4=0; - RA_template->wait_ack_Msg4=1; - - // increment Absolute subframe by 8 for Msg4 retransmission - LOG_D(MAC,"Frame %d, Subframe %d: Preparing for Msg4 retransmission currently %d.%d\n", - frameP,subframeP,RA_template->Msg4_frame,RA_template->Msg4_subframe); - if (RA_template->Msg4_subframe > 1) RA_template->Msg4_frame++; - RA_template->Msg4_frame&=1023; - RA_template->Msg4_subframe = (RA_template->Msg4_subframe+8)%10; - LOG_D(MAC,"Frame %d, Subframe %d: Msg4 retransmission in %d.%d\n", - frameP,subframeP,RA_template->Msg4_frame,RA_template->Msg4_subframe); - lcid=0; - - // put HARQ process round to 0 - if (cc->tdd_Config) RA_template->harq_pid = ((frameP*10)+subframeP)%10; - else RA_template->harq_pid = ((frameP*10)+subframeP)&7; - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][RA_template->harq_pid] = 0; - - if ((RA_template->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { - msg4_padding = RA_template->msg4_TBsize - rrc_sdu_length - msg4_header; - msg4_post_padding = 0; - } else { - msg4_padding = 0; - msg4_post_padding = RA_template->msg4_TBsize - rrc_sdu_length - msg4_header -1; - } - - LOG_D(MAC,"[eNB %d][RAPROC] CC_idP %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", - module_idP,CC_idP,frameP,subframeP,RA_template->msg4_TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); - DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return - // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] - offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], - 1, //num_sdus - (unsigned short*)&rrc_sdu_length, // - &lcid, // sdu_lcid - 255, // no drx - 31, // no timing advance - RA_template->cont_res_id, // contention res id - msg4_padding, // no padding - msg4_post_padding); - - memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], - &cc[CC_idP].CCCH_pdu.payload[0], - rrc_sdu_length); - - // DLSCH Config - fill_nfapi_dlsch_config(eNB, - dl_req, - RA_template->msg4_TBsize, - eNB->pdu_index[CC_idP], - RA_template->rnti, - 2, // resource_allocation_type : format 1A/1B/1D - 0, // virtual_resource_block_assignment_flag : localized - getRIV(N_RB_DL,first_rb,4), // resource_block_coding : RIV, 4 PRB - 2, // modulation: QPSK - 0, // redundancy version - 1, // transport_blocks - 0, // transport_block_to_codeword_swap_flag (0) - (cc->p_eNB==1 ) ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - //0, // codebook index - 1, // ue_category_capacity - 4, // pa: 0 dB - 0, // delta_power_offset_index - 0, // ngap - 1, // NPRB = 3 like in DCI - (cc->p_eNB==1 ) ? 1 : 2, // transmission mode - 1, // num_bf_prb_per_subband - 1); // num_bf_vector - LOG_D(MAC,"Filled DLSCH config, pdu number %d, non-dci pdu_index %d\n",dl_req->number_pdu,eNB->pdu_index[CC_idP]); - - // DL request - eNB->TX_req[CC_idP].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_idP].tx_request_body, - (frameP*10)+subframeP, - rrc_sdu_length, - eNB->pdu_index[CC_idP], - eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]); - eNB->pdu_index[CC_idP]++; - - LOG_D(MAC,"Filling UCI ACK/NAK information, cce_idx %d\n",dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // Program PUCCH1a for ACK/NAK - // Program ACK/NAK for Msg4 PDSCH - fill_nfapi_uci_acknak(module_idP, - CC_idP, - RA_template->rnti, - (frameP*10)+subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - - - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP), - T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], RA_template->msg4_TBsize)); - - if (opt_enabled==1) { - trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], - rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), - eNB->frame, eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", - module_idP, CC_idP, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); - } - - } // CCE Allocation feasible - } // msg4 frame/subframe - } // else rach_resource_type + } //repetition_count==0 && SF condition met + else if (ra->msg4_mpdcch_repetition_cnt > 0) { // we're in a stream of repetitions + ra->msg4_mpdcch_repetition_cnt++; + if (ra->msg4_mpdcch_repetition_cnt == reps) { // this is the last mpdcch repetition + if (cc[CC_idP].tdd_Config == NULL) { // FDD case + // wait 2 subframes for PDSCH transmission + if (subframeP > 7) + ra->Msg4_frame = (frameP + 1) & 1023; + else + ra->Msg4_frame = frameP; + ra->Msg4_subframe = (subframeP + 2) % 10; + } else { + AssertFatal(1 == 0, "TDD case not done yet\n"); + } + } // mpdcch_repetition_count == reps + if ((ra->Msg4_frame == frameP) + && (ra->Msg4_subframe == subframeP)) { + + // Program PDSCH + + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 BR with RRC Piggyback (ce_level %d RNTI %x)\n", + module_idP, CC_idP, frameP, subframeP, + ra->rach_resource_type - 1, ra->rnti); + + AssertFatal(1 == 0, + "Msg4 generation not finished for BL/CE UE\n"); + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + mac->pdu_index[CC_idP]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = ra->rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6); // check that this isn't getRIV(6,0,6) + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = + 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + transmission_scheme = (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = + 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = + (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = + cc[CC_idP]. + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13-> + startSymbolBR_r13; + + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = + (ra->rach_resource_type < 3) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13. + initial_transmission_sf_io = (10 * frameP) + subframeP; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = + 0; + dl_req->number_pdu++; + + ra->state = WAITMSG4ACK; + + lcid = 0; + + UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = + 0; + msg4_header = 1 + 6 + 1; // CR header, CR CE, SDU header + + if ((ra->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = + ra->msg4_TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = + ra->msg4_TBsize - rrc_sdu_length - msg4_header - 1; + } + + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP, CC_idP, frameP, subframeP, + ra->msg4_TBsize, rrc_sdu_length, msg4_header, + msg4_padding, msg4_post_padding); + DevAssert(UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return + // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] + offset = generate_dlsch_header((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus + (unsigned short *) &rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 31, // no timing advance + ra->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void *) &mac->UE_list. + DLSCH_pdu[CC_idP][0][(unsigned char) + UE_id].payload[0][(unsigned + char) + offset], + &cc[CC_idP].CCCH_pdu.payload[0], rrc_sdu_length); + + // DL request + mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP; + TX_req = + &mac->TX_req[CC_idP].tx_request_body.tx_pdu_list[mac-> + TX_req + [CC_idP]. + tx_request_body.number_of_pdus]; + TX_req->pdu_length = rrc_sdu_length; + TX_req->pdu_index = mac->pdu_index[CC_idP]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = rrc_sdu_length; + TX_req->segments[0].segment_data = + mac->UE_list. + DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0]; + mac->TX_req[CC_idP].tx_request_body.number_of_pdus++; + + // Program ACK/NAK for Msg4 PDSCH + int absSF = (ra->Msg3_frame * 10) + ra->Msg3_subframe; + // see Section 10.2 from 36.213 + int ackNAK_absSF = absSF + reps + 4; + AssertFatal(reps > 2, + "Have to handle programming of ACK when PDSCH repetitions is > 2\n"); + ul_req = + &mac->UL_req_tmp[CC_idP][ackNAK_absSF % + 10].ul_config_request_body; + ul_config_pdu = + &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; + + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_harq_pdu)); + ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0; // don't know how to use this + ul_config_pdu->uci_harq_pdu. + ue_information.ue_information_rel8.rnti = ra->rnti; + ul_config_pdu->uci_harq_pdu. + ue_information.ue_information_rel13.ue_type = + (ra->rach_resource_type < 3) ? 1 : 2; + ul_config_pdu->uci_harq_pdu. + ue_information.ue_information_rel13.empty_symbols = 0; + ul_config_pdu->uci_harq_pdu.ue_information. + ue_information_rel13.total_number_of_repetitions = + pucchreps[ra->rach_resource_type - 1]; + ul_config_pdu->uci_harq_pdu. + ue_information.ue_information_rel13.repetition_number = + 0; + // Note need to keep sending this across reptitions!!!! Not really for PUCCH, to ask small-cell forum, we'll see for the other messages, maybe parameters change across repetitions and FAPI has to provide for that + if (cc[CC_idP].tdd_Config == NULL) { // FDD case + ul_config_pdu->uci_harq_pdu. + harq_information.harq_information_rel8_fdd. + n_pucch_1_0 = + n1pucchan[ra->rach_resource_type - 1]; + // NOTE: How to fill in the rest of the n_pucch_1_0 information 213 Section 10.1.2.1 in the general case + // = N_ECCE_q + Delta_ARO + n1pucchan[ce_level] + // higher in the MPDCCH configuration, N_ECCE_q is hard-coded to 0, and harq resource offset to 0 => + // Delta_ARO = 0 from Table 10.1.2.1-1 + ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.harq_size = 1; // 1-bit ACK/NAK + } else { + AssertFatal(1 == 0, + "PUCCH configuration for ACK/NAK not handled yet for TDD BL/CE case\n"); + } + ul_req->number_of_pdus++; + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), + T_INT(CC_idP), T_INT(ra->rnti), T_INT(frameP), + T_INT(subframeP), T_INT(0 /*harq_pid always 0? */ ), + T_BUFFER(&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id]. + payload[0], ra->msg4_TBsize)); + + if (opt_enabled == 1) { + trace_pdu(1, + (uint8_t *) mac-> + UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) + UE_id].payload + [0], rrc_sdu_length, UE_id, 3, + UE_RNTI(module_idP, UE_id), mac->frame, + mac->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_idP, frameP, UE_RNTI(module_idP, + UE_id), + rrc_sdu_length); + } + } // Msg4 frame/subframe + } // msg4_mpdcch_repetition_count + } // rach_resource_type > 0 + else +#endif + { // This is normal LTE case + if ((ra->Msg4_frame == frameP) && (ra->Msg4_subframe == subframeP)) { + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n", + module_idP, CC_idP, frameP, subframeP, ra->rnti); + + /// Choose first 4 RBs for Msg4, should really check that these are free! + first_rb = 0; + + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + + + // Compute MCS/TBS for 3 PRB (coded on 4 vrb) + msg4_header = 1 + 6 + 1; // CR header, CR CE, SDU header + + if ((rrc_sdu_length + msg4_header) <= 22) { + ra->msg4_mcs = 4; + ra->msg4_TBsize = 22; + } else if ((rrc_sdu_length + msg4_header) <= 28) { + ra->msg4_mcs = 5; + ra->msg4_TBsize = 28; + } else if ((rrc_sdu_length + msg4_header) <= 32) { + ra->msg4_mcs = 6; + ra->msg4_TBsize = 32; + } else if ((rrc_sdu_length + msg4_header) <= 41) { + ra->msg4_mcs = 7; + ra->msg4_TBsize = 41; + } else if ((rrc_sdu_length + msg4_header) <= 49) { + ra->msg4_mcs = 8; + ra->msg4_TBsize = 49; + } else if ((rrc_sdu_length + msg4_header) <= 57) { + ra->msg4_mcs = 9; + ra->msg4_TBsize = 57; + } + + fill_nfapi_dl_dci_1A(dl_config_pdu, 4, // aggregation_level + ra->rnti, // rnti + 1, // rnti_type, CRNTI + ra->harq_pid, // harq_process + 1, // tpc, none + getRIV(N_RB_DL, first_rb, 4), // resource_block_coding + ra->msg4_mcs, // mcs + 1, // ndi + 0, // rv + 0); // vrb_flag + LOG_D(MAC, + "Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n", + frameP, subframeP, dl_req->number_pdu, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process, + &dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + resource_block_coding, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + resource_block_coding); + AssertFatal(dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_block_coding < 8192, + "resource_block_coding %u < 8192\n", + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_block_coding); + if (!CCE_allocation_infeasible + (module_idP, CC_idP, 1, subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, ra->rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + + ra->state = WAITMSG4ACK; + + // increment Absolute subframe by 8 for Msg4 retransmission + LOG_D(MAC, + "Frame %d, Subframe %d: Preparing for Msg4 retransmission currently %d.%d\n", + frameP, subframeP, ra->Msg4_frame, + ra->Msg4_subframe); + if (ra->Msg4_subframe > 1) + ra->Msg4_frame++; + ra->Msg4_frame &= 1023; + ra->Msg4_subframe = (ra->Msg4_subframe + 8) % 10; + LOG_D(MAC, + "Frame %d, Subframe %d: Msg4 retransmission in %d.%d\n", + frameP, subframeP, ra->Msg4_frame, + ra->Msg4_subframe); + lcid = 0; + + // put HARQ process round to 0 + if (cc->tdd_Config) + ra->harq_pid = ((frameP * 10) + subframeP) % 10; + else + ra->harq_pid = ((frameP * 10) + subframeP) & 7; + UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = + 0; + + if ((ra->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = + ra->msg4_TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = + ra->msg4_TBsize - rrc_sdu_length - msg4_header - 1; + } + + LOG_D(MAC, + "[eNB %d][RAPROC] CC_idP %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP, CC_idP, frameP, subframeP, + ra->msg4_TBsize, rrc_sdu_length, msg4_header, + msg4_padding, msg4_post_padding); + DevAssert(UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return + // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] + offset = generate_dlsch_header((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus + (unsigned short *) &rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 31, // no timing advance + ra->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void *) &mac->UE_list. + DLSCH_pdu[CC_idP][0][(unsigned char) + UE_id].payload[0][(unsigned + char) + offset], + &cc[CC_idP].CCCH_pdu.payload[0], rrc_sdu_length); + + // DLSCH Config + fill_nfapi_dlsch_config(mac, dl_req, ra->msg4_TBsize, mac->pdu_index[CC_idP], ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D + 0, // virtual_resource_block_assignment_flag : localized + getRIV(N_RB_DL, first_rb, 4), // resource_block_coding : RIV, 4 PRB + 2, // modulation: QPSK + 0, // redundancy version + 1, // transport_blocks + 0, // transport_block_to_codeword_swap_flag (0) + (cc->p_eNB == 1) ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + //0, // codebook index + 1, // ue_category_capacity + 4, // pa: 0 dB + 0, // delta_power_offset_index + 0, // ngap + 1, // NPRB = 3 like in DCI + (cc->p_eNB == 1) ? 1 : 2, // transmission mode + 1, // num_bf_prb_per_subband + 1); // num_bf_vector + LOG_D(MAC, + "Filled DLSCH config, pdu number %d, non-dci pdu_index %d\n", + dl_req->number_pdu, mac->pdu_index[CC_idP]); + + // DL request + mac->TX_req[CC_idP].sfn_sf = + fill_nfapi_tx_req(&mac->TX_req[CC_idP].tx_request_body, + (frameP * 10) + subframeP, + rrc_sdu_length, + mac->pdu_index[CC_idP], + mac->UE_list. + DLSCH_pdu[CC_idP][0][(unsigned char) + UE_id].payload + [0]); + mac->pdu_index[CC_idP]++; + + LOG_D(MAC, "Filling UCI ACK/NAK information, cce_idx %d\n", + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + // Program PUCCH1a for ACK/NAK + // Program ACK/NAK for Msg4 PDSCH + fill_nfapi_uci_acknak(module_idP, + CC_idP, + ra->rnti, + (frameP * 10) + subframeP, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.cce_idx); + + + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), + T_INT(CC_idP), T_INT(ra->rnti), T_INT(frameP), + T_INT(subframeP), T_INT(0 /*harq_pid always 0? */ ), + T_BUFFER(&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id]. + payload[0], ra->msg4_TBsize)); + + if (opt_enabled == 1) { + trace_pdu(1, + (uint8_t *) mac-> + UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) + UE_id].payload + [0], rrc_sdu_length, UE_id, 3, + UE_RNTI(module_idP, UE_id), mac->frame, + mac->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_idP, frameP, UE_RNTI(module_idP, + UE_id), + rrc_sdu_length); + } + + } // CCE Allocation feasible + } // msg4 frame/subframe + } // else rach_resource_type } -void check_Msg4_retransmission(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template) { - - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - int UE_id = -1; - uint8_t *vrb_map; - int first_rb; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - UE_list_t *UE_list=&eNB->UE_list; - nfapi_dl_config_request_body_t *dl_req; - - int round; - /* +void +check_Msg4_retransmission(module_id_t module_idP, int CC_idP, + frame_t frameP, sub_frame_t subframeP, RA_t * ra) +{ + + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + int UE_id = -1; + uint8_t *vrb_map; + int first_rb; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + UE_list_t *UE_list = &mac->UE_list; + nfapi_dl_config_request_body_t *dl_req; + + int round; + /* + #ifdef Rel14 + COMMON_channels_t *cc = mac->common_channels; + + int rmax = 0; + int rep = 0; + int reps = 0; + + first_rb = 0; + struct PRACH_ConfigSIB_v1310 *ext4_prach; + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; + PRACH_ParametersCE_r13_t *p[4]; + + if (cc[CC_idP].radioResourceConfigCommon_BR) { + + ext4_prach = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; + prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; + + switch (prach_ParametersListCE_r13->list.count) { + case 4: + p[3]=prach_ParametersListCE_r13->list.array[3]; + case 3: + p[2]=prach_ParametersListCE_r13->list.array[2]; + case 2: + p[1]=prach_ParametersListCE_r13->list.array[1]; + case 1: + p[0]=prach_ParametersListCE_r13->list.array[0]; + default: + AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count); + } + } + #endif + */ + + // check HARQ status and retransmit if necessary + + + UE_id = find_UE_id(module_idP, ra->rnti); + AssertFatal(UE_id >= 0, "Can't find UE for t-crnti\n"); + + round = UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid]; + vrb_map = cc[CC_idP].vrb_map; + + dl_req = &mac->DL_req[CC_idP].dl_config_request_body; + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); + + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 for harq_pid %d was acknowledged (round %d)\n", + module_idP, CC_idP, frameP, subframeP, ra->harq_pid, round); + + if (round != 8) { + #ifdef Rel14 - COMMON_channels_t *cc = eNB->common_channels; - - int rmax = 0; - int rep = 0; - int reps = 0; - - first_rb = 0; - struct PRACH_ConfigSIB_v1310 *ext4_prach; - PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13; - PRACH_ParametersCE_r13_t *p[4]; - - if (cc[CC_idP].radioResourceConfigCommon_BR) { - - ext4_prach = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; - prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; - - switch (prach_ParametersListCE_r13->list.count) { - case 4: - p[3]=prach_ParametersListCE_r13->list.array[3]; - case 3: - p[2]=prach_ParametersListCE_r13->list.array[2]; - case 2: - p[1]=prach_ParametersListCE_r13->list.array[1]; - case 1: - p[0]=prach_ParametersListCE_r13->list.array[0]; - default: - AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count); - } - } + if (ra->rach_resource_type > 0) { + AssertFatal(1 == 0, + "Msg4 Retransmissions not handled yet for BL/CE UEs\n"); + } else #endif - */ - - // check HARQ status and retransmit if necessary - - - UE_id = find_UE_id(module_idP,RA_template->rnti); - AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); - - round = UE_list->UE_sched_ctrl[UE_id].round[CC_idP][RA_template->harq_pid]; - vrb_map = cc[CC_idP].vrb_map; - - dl_req = &eNB->DL_req[CC_idP].dl_config_request_body; - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth); - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 for harq_pid %d was acknowledged (round %d)\n", - module_idP,CC_idP,frameP,subframeP,RA_template->harq_pid,round); - - if (round!=8) { - -#ifdef Rel14 - if (RA_template->rach_resource_type>0) { - AssertFatal(1==0,"Msg4 Retransmissions not handled yet for BL/CE UEs\n"); + { + if ((ra->Msg4_frame == frameP) + && (ra->Msg4_subframe == subframeP)) { + + //ra->wait_ack_Msg4++; + // we have to schedule a retransmission + + first_rb = 0; + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + + fill_nfapi_dl_dci_1A(dl_config_pdu, 4, // aggregation_level + ra->rnti, // rnti + 1, // rnti_type, CRNTI + ra->harq_pid, // harq_process + 1, // tpc, none + getRIV(N_RB_DL, first_rb, 4), // resource_block_coding + ra->msg4_mcs, // mcs + 1, // ndi + round & 3, // rv + 0); // vrb_flag + + if (!CCE_allocation_infeasible + (module_idP, CC_idP, 1, subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, ra->rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + + LOG_D(MAC, + "msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", + ra->rnti, round, frameP, subframeP); + // DLSCH Config + fill_nfapi_dlsch_config(mac, dl_req, ra->msg4_TBsize, + -1 + /* retransmission, no pdu_index */ + , ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D + 0, // virtual_resource_block_assignment_flag : localized + getRIV(N_RB_DL, first_rb, 4), // resource_block_coding : RIV, 4 PRB + 2, // modulation: QPSK + round & 3, // redundancy version + 1, // transport_blocks + 0, // transport_block_to_codeword_swap_flag (0) + (cc->p_eNB == 1) ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + //0, // codebook index + 1, // ue_category_capacity + 4, // pa: 0 dB + 0, // delta_power_offset_index + 0, // ngap + 1, // NPRB = 3 like in DCI + (cc->p_eNB == 1) ? 1 : 2, // transmission mode + 1, // num_bf_prb_per_subband + 1); // num_bf_vector + } else + LOG_D(MAC, + "msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", + ra->rnti, round, frameP, subframeP); + + + // Program PUCCH1a for ACK/NAK + + + fill_nfapi_uci_acknak(module_idP, CC_idP, + ra->rnti, + (frameP * 10) + subframeP, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.cce_idx); + + // prepare frame for retransmission + if (ra->Msg4_subframe > 1) + ra->Msg4_frame++; + ra->Msg4_frame &= 1023; + ra->Msg4_subframe = (ra->Msg4_subframe + 8) % 10; + + LOG_W(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission round %d in %d.%d)\n", + module_idP, CC_idP, frameP, subframeP, ra->rnti, + round, ra->Msg4_frame, ra->Msg4_subframe); + + } // Msg4 frame/subframe + } // regular LTE case + } else { + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n", + module_idP, CC_idP, frameP, subframeP); + ra->state = IDLE; + UE_id = find_UE_id(module_idP, ra->rnti); + DevAssert(UE_id != -1); + mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id]. + configured = TRUE; } - else -#endif - { - if ( (RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { - - //RA_template->wait_ack_Msg4++; - // we have to schedule a retransmission - - first_rb=0; - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - fill_nfapi_dl_dci_1A(dl_config_pdu, - 4, // aggregation_level - RA_template->rnti, // rnti - 1, // rnti_type, CRNTI - RA_template->harq_pid, // harq_process - 1, // tpc, none - getRIV(N_RB_DL,first_rb,4), // resource_block_coding - RA_template->msg4_mcs, // mcs - 1, // ndi - round&3, // rv - 0); // vrb_flag - - if (!CCE_allocation_infeasible(module_idP,CC_idP,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - - LOG_D(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP); - // DLSCH Config - fill_nfapi_dlsch_config(eNB, - dl_req, - RA_template->msg4_TBsize, - -1 /* retransmission, no pdu_index */, - RA_template->rnti, - 2, // resource_allocation_type : format 1A/1B/1D - 0, // virtual_resource_block_assignment_flag : localized - getRIV(N_RB_DL,first_rb,4), // resource_block_coding : RIV, 4 PRB - 2, // modulation: QPSK - round&3, // redundancy version - 1, // transport_blocks - 0, // transport_block_to_codeword_swap_flag (0) - (cc->p_eNB==1 ) ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - //0, // codebook index - 1, // ue_category_capacity - 4, // pa: 0 dB - 0, // delta_power_offset_index - 0, // ngap - 1, // NPRB = 3 like in DCI - (cc->p_eNB==1 ) ? 1 : 2, // transmission mode - 1, // num_bf_prb_per_subband - 1); // num_bf_vector - } - else - LOG_D(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP); - - - // Program PUCCH1a for ACK/NAK - - - fill_nfapi_uci_acknak(module_idP,CC_idP, - RA_template->rnti, - (frameP*10)+subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - - // prepare frame for retransmission - if (RA_template->Msg4_subframe>1) RA_template->Msg4_frame++; - RA_template->Msg4_frame&=1023; - RA_template->Msg4_subframe=(RA_template->Msg4_subframe+8)%10; - - LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission round %d in %d.%d)\n", - module_idP,CC_idP,frameP,subframeP,RA_template->rnti,round,RA_template->Msg4_frame,RA_template->Msg4_subframe); - - } // Msg4 frame/subframe - } // regular LTE case - } else { - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_idP,frameP,subframeP); - RA_template->wait_ack_Msg4=0; - RA_template->RA_active=FALSE; - UE_id = find_UE_id(module_idP,RA_template->rnti); - DevAssert( UE_id != -1 ); - eNB->UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; - } -} - -void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP) -{ - - int CC_id; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - RA_TEMPLATE *RA_template; - uint8_t i; +} - start_meas(&eNB->schedule_ra); +void +schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) +{ + int CC_id; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + RA_t *ra; + uint8_t i; - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - // skip UL component carriers if TDD - if (is_UL_sf(&cc[CC_id],subframeP)==1) continue; + start_meas(&mac->schedule_ra); - for (i=0; i<NB_RA_PROC_MAX; i++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + // skip UL component carriers if TDD + if (is_UL_sf(&cc[CC_id], subframeP) == 1) + continue; - RA_template = (RA_TEMPLATE *)&cc[CC_id].RA_template[i]; - if (RA_template->RA_active == TRUE) { + for (i = 0; i < NB_RA_PROC_MAX; i++) { - LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n", - module_idP,frameP,subframeP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti); + ra = (RA_t *) & cc[CC_id].ra[i]; - if (RA_template->generate_rar == 1) generate_Msg2(module_idP,CC_id,frameP,subframeP,RA_template); - else if (RA_template->generate_Msg4 == 1) generate_Msg4(module_idP,CC_id,frameP,subframeP,RA_template); - else if (RA_template->wait_ack_Msg4==1) check_Msg4_retransmission(module_idP,CC_id,frameP,subframeP,RA_template); + if (ra->state == MSG2) + generate_Msg2(module_idP, CC_id, frameP, subframeP, ra); + else if (ra->state == MSG4) + generate_Msg4(module_idP, CC_id, frameP, subframeP, ra); + else if (ra->state == WAITMSG4ACK) + check_Msg4_retransmission(module_idP, CC_id, frameP, + subframeP, ra); + } // for i=0 .. N_RA_PROC-1 + } // CC_id - } // RA_active == TRUE - } // for i=0 .. N_RA_PROC-1 - } // CC_id - - stop_meas(&eNB->schedule_ra); + stop_meas(&mac->schedule_ra); } // handles the event of MSG1 reception -void initiate_ra_proc(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t subframeP, - uint16_t preamble_index, - int16_t timing_offset, - uint16_t ra_rnti +void +initiate_ra_proc(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframeP, + uint16_t preamble_index, + int16_t timing_offset, uint16_t ra_rnti #ifdef Rel14 - , - uint8_t rach_resource_type + , uint8_t rach_resource_type #endif - ) + ) { - uint8_t i; + uint8_t i; - COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; - RA_TEMPLATE *RA_template = &cc->RA_template[0]; + COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; + RA_t *ra = &cc->ra[0]; - struct PRACH_ConfigSIB_v1310 *ext4_prach = NULL; - PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = NULL; + struct PRACH_ConfigSIB_v1310 *ext4_prach = NULL; + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = NULL; - if (cc->radioResourceConfigCommon_BR && cc->radioResourceConfigCommon_BR->ext4) { - ext4_prach=cc->radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; - prach_ParametersListCE_r13= &ext4_prach->prach_ParametersListCE_r13; - } - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,subframeP,preamble_index); + if (cc->radioResourceConfigCommon_BR + && cc->radioResourceConfigCommon_BR->ext4) { + ext4_prach = + cc->radioResourceConfigCommon_BR->ext4-> + prach_ConfigCommon_v1310; + prach_ParametersListCE_r13 = + &ext4_prach->prach_ParametersListCE_r13; + } + LOG_I(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d Initiating RA procedure for preamble index %d\n", + module_idP, CC_id, frameP, subframeP, preamble_index); #ifdef Rel14 - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d PRACH resource type %d\n",module_idP,CC_id,frameP,subframeP,rach_resource_type); + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d PRACH resource type %d\n", + module_idP, CC_id, frameP, subframeP, rach_resource_type); #endif - if (prach_ParametersListCE_r13 && - prach_ParametersListCE_r13->list.count<rach_resource_type) { - LOG_E(MAC,"[eNB %d][RAPROC] CC_id %d Received impossible PRACH resource type %d, only %d CE levels configured\n", - module_idP,CC_id, - rach_resource_type, - (int)prach_ParametersListCE_r13->list.count); - return; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0); - - for (i=0; i<NB_RA_PROC_MAX; i++) { - if (RA_template[i].RA_active==FALSE && - RA_template[i].wait_ack_Msg4 == 0) { - int loop = 0; - LOG_D(MAC,"Frame %d, Subframe %d: Activating RA process %d\n",frameP,subframeP,i); - RA_template[i].RA_active = TRUE; - RA_template[i].generate_rar = 1; - RA_template[i].generate_Msg4 = 0; - RA_template[i].wait_ack_Msg4 = 0; - RA_template[i].timing_offset = timing_offset; - RA_template[i].preamble_subframe = subframeP; + if (prach_ParametersListCE_r13 && + prach_ParametersListCE_r13->list.count < rach_resource_type) { + LOG_E(MAC, + "[eNB %d][RAPROC] CC_id %d Received impossible PRACH resource type %d, only %d CE levels configured\n", + module_idP, CC_id, rach_resource_type, + (int) prach_ParametersListCE_r13->list.count); + return; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); + + for (i = 0; i < NB_RA_PROC_MAX; i++) { + if (ra[i].state == IDLE) { + int loop = 0; + LOG_D(MAC, "Frame %d, Subframe %d: Activating RA process %d\n", + frameP, subframeP, i); + ra[i].state = MSG2; + ra[i].timing_offset = timing_offset; + ra[i].preamble_subframe = subframeP; #ifdef Rel14 - RA_template[i].rach_resource_type = rach_resource_type; - RA_template[i].msg2_mpdcch_repetition_cnt = 0; - RA_template[i].msg4_mpdcch_repetition_cnt = 0; + ra[i].rach_resource_type = rach_resource_type; + ra[i].msg2_mpdcch_repetition_cnt = 0; + ra[i].msg4_mpdcch_repetition_cnt = 0; #endif - RA_template[i].Msg2_frame = frameP+((subframeP>5)?1:0); - RA_template[i].Msg2_subframe = (subframeP+4)%10; - /* TODO: find better procedure to allocate RNTI */ - do { + ra[i].Msg2_frame = frameP + ((subframeP > 5) ? 1 : 0); + ra[i].Msg2_subframe = (subframeP + 4) % 10; + /* TODO: find better procedure to allocate RNTI */ + do { #if defined(USRP_REC_PLAY) // deterministic rnti in usrp record/playback mode - static int drnti[NUMBER_OF_UE_MAX] = { 0xbda7, 0x71da, 0x9c40, 0xc350, 0x2710, 0x4e20, 0x7530, 0x1388, 0x3a98, 0x61a8, 0x88b8, 0xafc8, 0xd6d8, 0x1b58, 0x4268, 0x6978 }; - int j = 0; - int nb_ue = 0; - for (j = 0; j < NUMBER_OF_UE_MAX; j++) { - if (UE_RNTI(module_idP, j) > 0) { - nb_ue++; - } else { - break; - } - } - if (nb_ue >= NUMBER_OF_UE_MAX) { - printf("No more free RNTI available, increase NUMBER_OF_UE_MAX\n"); - abort(); - } - RA_template[i].rnti = drnti[nb_ue]; + static int drnti[NUMBER_OF_UE_MAX] = { 0xbda7, 0x71da, 0x9c40, 0xc350, 0x2710, 0x4e20, 0x7530, 0x1388, 0x3a98, 0x61a8, 0x88b8, 0xafc8, 0xd6d8, 0x1b58, 0x4268, 0x6978 }; + int j = 0; + int nb_ue = 0; + for (j = 0; j < NUMBER_OF_UE_MAX; j++) { + if (UE_RNTI(module_idP, j) > 0) { + nb_ue++; + } else { + break; + } + } + if (nb_ue >= NUMBER_OF_UE_MAX) { + printf("No more free RNTI available, increase NUMBER_OF_UE_MAX\n"); + abort(); + } + ra[i].rnti = drnti[nb_ue]; #else - RA_template[i].rnti = taus(); + ra[i].rnti = taus(); #endif - loop++; - } while (loop != 100 && - /* TODO: this is not correct, the rnti may be in use without - * being in the MAC yet. To be refined. - */ - !(find_UE_id(module_idP, RA_template[i].rnti) == -1 && - /* 1024 and 60000 arbirarily chosen, not coming from standard */ - RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000)); - if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); } - RA_template[i].RA_rnti = ra_rnti; - RA_template[i].preamble_index = preamble_index; - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation in Frame %d, subframe %d for process %d, rnti %x, RA_active %d\n", - module_idP,CC_id,frameP, - RA_template[i].Msg2_frame, - RA_template[i].Msg2_subframe, - i,RA_template[i].rnti, - RA_template[i].RA_active); - - return; + loop++; + } + while (loop != 100 && + /* TODO: this is not correct, the rnti may be in use without + * being in the MAC yet. To be refined. + */ + !(find_UE_id(module_idP, ra[i].rnti) == -1 && + /* 1024 and 60000 arbirarily chosen, not coming from standard */ + ra[i].rnti >= 1024 && ra[i].rnti < 60000)); + if (loop == 100) { + printf("%s:%d:%s: FATAL ERROR! contact the authors\n", + __FILE__, __LINE__, __FUNCTION__); + abort(); + } + ra[i].RA_rnti = ra_rnti; + ra[i].preamble_index = preamble_index; + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation in Frame %d, subframe %d for process %d, rnti %x, state %d\n", + module_idP, CC_id, frameP, ra[i].Msg2_frame, + ra[i].Msg2_subframe, i, ra[i].rnti, ra[i].state); + + return; + } } - } - LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index); + LOG_E(MAC, + "[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n", + module_idP, CC_id, frameP, preamble_index); } -void cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, rnti_t rnti) +void +cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, + rnti_t rnti) { - unsigned char i; - RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[module_idP]->common_channels[CC_id].RA_template[0]; - - MSC_LOG_EVENT(MSC_PHY_ENB, "RA Cancelling procedure ue %"PRIx16" ", rnti); - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Cancelling RA procedure for UE rnti %x\n",module_idP,CC_id,frameP,rnti); - - for (i=0; i<NB_RA_PROC_MAX; i++) { - if (rnti == RA_template[i].rnti) { - RA_template[i].RA_active=FALSE; - RA_template[i].generate_rar=0; - RA_template[i].generate_Msg4=0; - RA_template[i].wait_ack_Msg4=0; - RA_template[i].timing_offset=0; - RA_template[i].RRC_timer=20; - RA_template[i].rnti = 0; - RA_template[i].msg3_round = 0; + unsigned char i; + RA_t *ra = (RA_t *) & RC.mac[module_idP]->common_channels[CC_id].ra[0]; + + MSC_LOG_EVENT(MSC_PHY_ENB, "RA Cancelling procedure ue %" PRIx16 " ", + rnti); + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d Cancelling RA procedure for UE rnti %x\n", + module_idP, CC_id, frameP, rnti); + + for (i = 0; i < NB_RA_PROC_MAX; i++) { + if (rnti == ra[i].rnti) { + ra[i].state = IDLE; + ra[i].timing_offset = 0; + ra[i].RRC_timer = 20; + ra[i].rnti = 0; + ra[i].msg3_round = 0; + } } - } } - diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index afc1141a222a52db31b00c07c1c37e117d77f854..71be9f9b9d7aa970e9c45377bc159a1c8c37f269 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -52,7 +52,7 @@ #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #define ENABLE_MAC_PAYLOAD_DEBUG @@ -65,714 +65,822 @@ #ifdef Rel14 #define size_Sj25 2 -int Sj25[size_Sj25]={0,3}; +int Sj25[size_Sj25] = { 0, 3 }; + #define size_Sj50 6 -int Sj50[size_Sj50]={0,1,2,5,6,7}; +int Sj50[size_Sj50] = { 0, 1, 2, 5, 6, 7 }; + #define size_Sj75 10 -int Sj75[size_Sj75]={0,1,2,3,4,7,8,9,10,11}; +int Sj75[size_Sj75] = { 0, 1, 2, 3, 4, 7, 8, 9, 10, 11 }; + #define size_Sj100 14 -int Sj100[size_Sj100]={0,1,2,3,4,5,6,9,10,11,12,13,14,15}; +int Sj100[size_Sj100] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15 }; -int SIB1_BR_TBS_table[6] = {208,256,328,504,712,936}; +int SIB1_BR_TBS_table[6] = { 208, 256, 328, 504, 712, 936 }; //------------------------------------------------------------------------------ void -schedule_SIB1_BR( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP) - +schedule_SIB1_BR(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int8_t bcch_sdu_length; - int CC_id; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc; - uint8_t *vrb_map; - int first_rb = -1; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - nfapi_dl_config_request_body_t *dl_req; - int m,i,N_S_NB; - int *Sj; - int n_NB = 0; - int TBS; - int k=0,rvidx; - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - cc = &eNB->common_channels[CC_id]; - vrb_map = (void*)&cc->vrb_map; - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - - int foffset = cc->physCellId&1; - int sfoffset = (cc->tdd_Config==NULL) ? 0 : 1; - - // Time-domain scheduling - if (cc->mib->message.schedulingInfoSIB1_BR_r13==0) continue; - else - switch ((cc->mib->message.schedulingInfoSIB1_BR_r13-1)%3) { - case 0: // repetition 4 - k = (frameP>>1)&3; - if ((subframeP!=(4+sfoffset)) || ((frameP&1)!=foffset)) continue; - break; - case 1: // repetition 8 - k = frameP&3; - AssertFatal(N_RB_DL>15,"SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n",N_RB_DL); - if ((foffset==0) && (subframeP!=(4+sfoffset))) continue; - else if ((foffset==1) && (subframeP!=((9+sfoffset)%10))) continue; - break; - case 2: // repetition 16 - k = ((10*frameP) + subframeP)&3; - AssertFatal(N_RB_DL>15,"SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n",N_RB_DL); - if ((sfoffset == 1) && ((subframeP!=0)||(subframeP!=5))) continue; - else if ((sfoffset == 0) && (foffset==0) && (subframeP!=4) && (subframeP!=9)) continue; - else if ((sfoffset == 0) && (foffset==1) && (subframeP!=0) && (subframeP!=9)) continue; - break; - } - // if we get here we have to schedule SIB1_BR in this frame/subframe - - // keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit - if ((frameP&7) == 0) cc->SIB1_BR_cnt=0; - else cc->SIB1_BR_cnt++; - - // Frequency-domain scheduling - switch (N_RB_DL) { - case 6: - case 15: - default: - m=1; - n_NB=0; - N_S_NB=0; - Sj=NULL; - break; - case 25: - m=2; - N_S_NB = 2; - Sj = Sj25; - break; - case 50: - m=2; - N_S_NB = 6; - Sj = Sj50; - break; - case 75: - m=4; - N_S_NB = 10; - Sj = Sj75; - break; - case 100: - m=4; - N_S_NB = 14; - Sj = Sj100; - break; - } - // Note: definition of k above and rvidx from 36.321 section 5.3.1 - rvidx = (((3*k)>>1) + (k&1))&3; - - i = cc->SIB1_BR_cnt & (m-1); - - n_NB = Sj[((cc->physCellId % N_S_NB) + (i*N_S_NB/m))%N_S_NB]; - - - bcch_sdu_length = mac_rrc_data_req(module_idP, - CC_id, - frameP, - BCCH_SIB1_BR,1, - &cc->BCCH_BR_pdu[0].payload[0], - 1, - module_idP, - 0); // not used in this case - - AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13<19,"schedulingInfoSIB1_BR_r13 %d > 18\n", - (int)cc->mib->message.schedulingInfoSIB1_BR_r13); - - AssertFatal(bcch_sdu_length>0,"RRC returned 0 bytes for SIB1-BR\n"); - - TBS = SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13-1)/3]>>3; - - AssertFatal(bcch_sdu_length <= TBS, "length returned by RRC %d is not compatible with the TBS %d from MIB\n",bcch_sdu_length,TBS); - - if ((frameP&1023) < 200) LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n",module_idP,frameP,subframeP,CC_id,bcch_sdu_length,n_NB,i,m,N_S_NB,rvidx); - - // allocate all 6 PRBs in narrowband for SIB1_BR - - first_rb = narrowband_to_first_rb(cc,n_NB); - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - vrb_map[first_rb+4] = 1; - vrb_map[first_rb+5] = 1; - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // Rel10 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; - // Rel13 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx - - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - dl_req->number_pdu++; - - // Program TX Request - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = bcch_sdu_length; - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = bcch_sdu_length; - TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; - - - - if (opt_enabled == 1) { - trace_pdu(1, - &cc->BCCH_BR_pdu[0].payload[0], - bcch_sdu_length, - 0xffff, - 4, - 0xffff, - eNB->frame, - eNB->subframe, - 0, - 0); - LOG_D(OPT,"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", - module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); - } - if (cc->tdd_Config!=NULL) { //TDD - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n", - frameP, - CC_id, - bcch_sdu_length); - } else { - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n", - frameP, - CC_id, - bcch_sdu_length); - } + int8_t bcch_sdu_length; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int first_rb = -1; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; + int m, i, N_S_NB; + int *Sj; + int n_NB = 0; + int TBS; + int k = 0, rvidx; + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + vrb_map = (void *) &cc->vrb_map; + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + int foffset = cc->physCellId & 1; + int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1; + + // Time-domain scheduling + if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0) + continue; + else + switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) { + case 0: // repetition 4 + k = (frameP >> 1) & 3; + if ((subframeP != (4 + sfoffset)) + || ((frameP & 1) != foffset)) + continue; + break; + case 1: // repetition 8 + k = frameP & 3; + AssertFatal(N_RB_DL > 15, + "SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n", + N_RB_DL); + if ((foffset == 0) && (subframeP != (4 + sfoffset))) + continue; + else if ((foffset == 1) + && (subframeP != ((9 + sfoffset) % 10))) + continue; + break; + case 2: // repetition 16 + k = ((10 * frameP) + subframeP) & 3; + AssertFatal(N_RB_DL > 15, + "SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n", + N_RB_DL); + if ((sfoffset == 1) + && ((subframeP != 0) || (subframeP != 5))) + continue; + else if ((sfoffset == 0) && (foffset == 0) + && (subframeP != 4) && (subframeP != 9)) + continue; + else if ((sfoffset == 0) && (foffset == 1) + && (subframeP != 0) && (subframeP != 9)) + continue; + break; + } + // if we get here we have to schedule SIB1_BR in this frame/subframe + + // keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit + if ((frameP & 7) == 0) + cc->SIB1_BR_cnt = 0; + else + cc->SIB1_BR_cnt++; + + // Frequency-domain scheduling + switch (N_RB_DL) { + case 6: + case 15: + default: + m = 1; + n_NB = 0; + N_S_NB = 0; + Sj = NULL; + break; + case 25: + m = 2; + N_S_NB = 2; + Sj = Sj25; + break; + case 50: + m = 2; + N_S_NB = 6; + Sj = Sj50; + break; + case 75: + m = 4; + N_S_NB = 10; + Sj = Sj75; + break; + case 100: + m = 4; + N_S_NB = 14; + Sj = Sj100; + break; + } + // Note: definition of k above and rvidx from 36.321 section 5.3.1 + rvidx = (((3 * k) >> 1) + (k & 1)) & 3; + + i = cc->SIB1_BR_cnt & (m - 1); + + n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB]; + + + bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 1, &cc->BCCH_BR_pdu[0].payload[0], 1, module_idP, 0); // not used in this case + + AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19, + "schedulingInfoSIB1_BR_r13 %d > 18\n", + (int) cc->mib->message.schedulingInfoSIB1_BR_r13); + + AssertFatal(bcch_sdu_length > 0, + "RRC returned 0 bytes for SIB1-BR\n"); + + TBS = + SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 - + 1) / 3] >> 3; + + AssertFatal(bcch_sdu_length <= TBS, + "length returned by RRC %d is not compatible with the TBS %d from MIB\n", + bcch_sdu_length, TBS); + + if ((frameP & 1023) < 200) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n", + module_idP, frameP, subframeP, CC_id, bcch_sdu_length, + n_NB, i, m, N_S_NB, rvidx); + + // allocate all 6 PRBs in narrowband for SIB1_BR + + first_rb = narrowband_to_first_rb(cc, n_NB); + + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + vrb_map[first_rb + 4] = 1; + vrb_map[first_rb + 5] = 1; + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = + getRIV(N_RB_DL, first_rb, 6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = + (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = + 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = + (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx + + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Program TX Request + TX_req = + &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB-> + TX_req + [CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = bcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = bcch_sdu_length; + TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + + + + if (opt_enabled == 1) { + trace_pdu(1, + &cc->BCCH_BR_pdu[0].payload[0], + bcch_sdu_length, + 0xffff, 4, 0xffff, eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); + } + if (cc->tdd_Config != NULL) { //TDD + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n", + frameP, CC_id, bcch_sdu_length); + } else { + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n", + frameP, CC_id, bcch_sdu_length); + } - } + } - return; + return; } -int si_WindowLength_BR_r13tab[SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_spare] = - {20,40,60,80,120,160,200}; -int si_TBS_r13tab[SchedulingInfo_BR_r13__si_TBS_r13_b936+1] = {152,208,256,328,408,504,600,712,808,936}; +int si_WindowLength_BR_r13tab + [SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_spare] += { 20, 40, 60, 80, 120, 160, 200 }; +int si_TBS_r13tab[SchedulingInfo_BR_r13__si_TBS_r13_b936 + 1] = + { 152, 208, 256, 328, 408, 504, 600, 712, 808, 936 }; //------------------------------------------------------------------------------ void -schedule_SI_BR( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP) - +schedule_SI_BR(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int8_t bcch_sdu_length; - int CC_id; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc; - uint8_t *vrb_map; - int first_rb = -1; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - nfapi_dl_config_request_body_t *dl_req; - int i; - int rvidx; - int absSF = (frameP*10)+subframeP; - - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - cc = &eNB->common_channels[CC_id]; - vrb_map = (void*)&cc->vrb_map; - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - - // Time-domain scheduling - if (cc->mib->message.schedulingInfoSIB1_BR_r13==0) continue; - else { - - - AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, - "sib_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); - - SchedulingInfoList_BR_r13_t *schedulingInfoList_BR_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->schedulingInfoList_BR_r13; - AssertFatal(schedulingInfoList_BR_r13!=NULL, - "sib_v13ext->schedulingInfoList_BR_r13 is null\n"); - - SchedulingInfoList_t *schedulingInfoList = cc->schedulingInfoList; - AssertFatal(schedulingInfoList_BR_r13->list.count==schedulingInfoList->list.count, - "schedulingInfolist_BR.r13->list.count %d != schedulingInfoList.list.count %d\n", - schedulingInfoList_BR_r13->list.count,schedulingInfoList->list.count); - - AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13<=SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200, - "si_WindowLength_BR_r13 %d > %d\n", - (int)cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13, - SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200); - - // check that SI frequency-hopping is disabled - AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_HoppingConfigCommon_r13==SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_HoppingConfigCommon_r13_off, - "Deactivate SI_HoppingConfigCommon_r13 in configuration file, not supported for now\n"); - long si_WindowLength_BR_r13 = si_WindowLength_BR_r13tab[cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13]; - - long si_RepetitionPattern_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_RepetitionPattern_r13; - AssertFatal(si_RepetitionPattern_r13<=SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF, - "si_RepetitionPattern_r13 %d > %d\n", - (int)si_RepetitionPattern_r13, - SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF); - // cycle through SIB list - - for (i=0;i<schedulingInfoList_BR_r13->list.count;i++) { - long si_Periodicity = schedulingInfoList->list.array[i]->si_Periodicity; - long si_Narrowband_r13 = schedulingInfoList_BR_r13->list.array[i]->si_Narrowband_r13; - long si_TBS_r13 = si_TBS_r13tab[schedulingInfoList_BR_r13->list.array[i]->si_TBS_r13]; - - // check if the SI is to be scheduled now - int period_in_sf = 80<<si_Periodicity; // 2^i * 80 subframes, note: si_Periodicity is 2^i * 80ms - int sf_mod_period = absSF%period_in_sf; - int k = sf_mod_period&3; - // Note: definition of k and rvidx from 36.321 section 5.3.1 - rvidx = (((3*k)>>1) + (k&1))&3; - - if ((sf_mod_period < si_WindowLength_BR_r13) && - ((frameP&(((1<<si_RepetitionPattern_r13)-1)))==0)) { // this SIB is to be scheduled - - bcch_sdu_length = mac_rrc_data_req(module_idP, - CC_id, - frameP, - BCCH_SI_BR+i,1, - &cc->BCCH_BR_pdu[i+1].payload[0], - 1, - module_idP, - 0); // not used in this case - - AssertFatal(bcch_sdu_length>0,"RRC returned 0 bytes for SI-BR %d\n",i); - - if (bcch_sdu_length > 0) { - AssertFatal(bcch_sdu_length <= (si_TBS_r13>>3), - "RRC provided bcch with length %d > %d (si_TBS_r13 %d)\n", - bcch_sdu_length,(int)(si_TBS_r13>>3),(int)schedulingInfoList_BR_r13->list.array[i]->si_TBS_r13); - - // allocate all 6 PRBs in narrowband for SIB1_BR - - // check that SIB1 didn't take this narrowband - if (vrb_map[first_rb] > 0) continue; - - first_rb = narrowband_to_first_rb(cc,si_Narrowband_r13-1); - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+4] = 1; - vrb_map[first_rb+5] = 1; - - if ((frameP&1023) < 200) LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: SI_BR->DLSCH CC_id %d, Narrowband %d rvidx %d (sf_mod_period %d : si_WindowLength_BR_r13 %d : si_RepetitionPattern_r13 %d) bcch_sdu_length %d\n", - module_idP,frameP,subframeP,CC_id,(int)si_Narrowband_r13-1,rvidx, - sf_mod_period,(int)si_WindowLength_BR_r13,(int)si_RepetitionPattern_r13, - bcch_sdu_length); - - - - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = si_TBS_r13>>3; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // Rel10 fields (for PDSCH starting symbol) - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; - // Rel13 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = absSF - sf_mod_period; - - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - dl_req->number_pdu++; - - // Program TX Request - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = bcch_sdu_length; - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = bcch_sdu_length; - TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[i+1].payload; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; - - if (opt_enabled == 1) { - trace_pdu(1, - &cc->BCCH_BR_pdu[i+1].payload[0], - bcch_sdu_length, - 0xffff, - 4, - 0xffff, - eNB->frame, - eNB->subframe, - 0, - 0); - LOG_D(OPT,"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", - module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); - } - if (cc->tdd_Config!=NULL) { //TDD - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (TDD) for CC_id %d SI-BR %d bytes\n", - frameP,i, - CC_id, - bcch_sdu_length); - } else { - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (FDD) for CC_id %d SI-BR %d bytes\n", - frameP,i, - CC_id, - bcch_sdu_length); - } - } - } // scheduling in current frame/subframe - } //for SI List - } // eMTC is activated - } // CC_id - return; + int8_t bcch_sdu_length; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int first_rb = -1; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; + int i; + int rvidx; + int absSF = (frameP * 10) + subframeP; + + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + vrb_map = (void *) &cc->vrb_map; + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + // Time-domain scheduling + if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0) + continue; + else { + + + AssertFatal(cc-> + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 + != NULL, + "sib_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); + + SchedulingInfoList_BR_r13_t *schedulingInfoList_BR_r13 = + cc->sib1_v13ext-> + bandwidthReducedAccessRelatedInfo_r13->schedulingInfoList_BR_r13; + AssertFatal(schedulingInfoList_BR_r13 != NULL, + "sib_v13ext->schedulingInfoList_BR_r13 is null\n"); + + SchedulingInfoList_t *schedulingInfoList = + cc->schedulingInfoList; + AssertFatal(schedulingInfoList_BR_r13->list.count == + schedulingInfoList->list.count, + "schedulingInfolist_BR.r13->list.count %d != schedulingInfoList.list.count %d\n", + schedulingInfoList_BR_r13->list.count, + schedulingInfoList->list.count); + + AssertFatal(cc-> + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13 + <= + SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200, + "si_WindowLength_BR_r13 %d > %d\n", + (int) cc-> + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13, + SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200); + + // check that SI frequency-hopping is disabled + AssertFatal(cc-> + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_HoppingConfigCommon_r13 + == + SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_HoppingConfigCommon_r13_off, + "Deactivate SI_HoppingConfigCommon_r13 in configuration file, not supported for now\n"); + long si_WindowLength_BR_r13 = + si_WindowLength_BR_r13tab[cc-> + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13]; + + long si_RepetitionPattern_r13 = + cc->sib1_v13ext-> + bandwidthReducedAccessRelatedInfo_r13->si_RepetitionPattern_r13; + AssertFatal(si_RepetitionPattern_r13 <= + SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF, + "si_RepetitionPattern_r13 %d > %d\n", + (int) si_RepetitionPattern_r13, + SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF); + // cycle through SIB list + + for (i = 0; i < schedulingInfoList_BR_r13->list.count; i++) { + long si_Periodicity = + schedulingInfoList->list.array[i]->si_Periodicity; + long si_Narrowband_r13 = + schedulingInfoList_BR_r13->list.array[i]-> + si_Narrowband_r13; + long si_TBS_r13 = + si_TBS_r13tab[schedulingInfoList_BR_r13-> + list.array[i]->si_TBS_r13]; + + // check if the SI is to be scheduled now + int period_in_sf = 80 << si_Periodicity; // 2^i * 80 subframes, note: si_Periodicity is 2^i * 80ms + int sf_mod_period = absSF % period_in_sf; + int k = sf_mod_period & 3; + // Note: definition of k and rvidx from 36.321 section 5.3.1 + rvidx = (((3 * k) >> 1) + (k & 1)) & 3; + + if ((sf_mod_period < si_WindowLength_BR_r13) + && ((frameP & (((1 << si_RepetitionPattern_r13) - 1))) == 0)) { // this SIB is to be scheduled + + bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_BR + i, 1, &cc->BCCH_BR_pdu[i + 1].payload[0], 1, module_idP, 0); // not used in this case + + AssertFatal(bcch_sdu_length > 0, + "RRC returned 0 bytes for SI-BR %d\n", i); + + if (bcch_sdu_length > 0) { + AssertFatal(bcch_sdu_length <= (si_TBS_r13 >> 3), + "RRC provided bcch with length %d > %d (si_TBS_r13 %d)\n", + bcch_sdu_length, + (int) (si_TBS_r13 >> 3), + (int) schedulingInfoList_BR_r13-> + list.array[i]->si_TBS_r13); + + // allocate all 6 PRBs in narrowband for SIB1_BR + + // check that SIB1 didn't take this narrowband + if (vrb_map[first_rb] > 0) + continue; + + first_rb = + narrowband_to_first_rb(cc, + si_Narrowband_r13 - 1); + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 4] = 1; + vrb_map[first_rb + 5] = 1; + + if ((frameP & 1023) < 200) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d: SI_BR->DLSCH CC_id %d, Narrowband %d rvidx %d (sf_mod_period %d : si_WindowLength_BR_r13 %d : si_RepetitionPattern_r13 %d) bcch_sdu_length %d\n", + module_idP, frameP, subframeP, CC_id, + (int) si_Narrowband_r13 - 1, rvidx, + sf_mod_period, + (int) si_WindowLength_BR_r13, + (int) si_RepetitionPattern_r13, + bcch_sdu_length); + + + + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req-> + number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = + NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = + si_TBS_r13 >> 3; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = + 0xFFFF; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.resource_block_coding = + getRIV(N_RB_DL, first_rb, 6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.redundancy_version = rvidx; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag + = 0; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transmission_scheme = + (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transmission_mode = + (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + num_bf_vector = 1; + // Rel10 fields (for PDSCH starting symbol) + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10. + pdsch_start = + cc[CC_id]. + sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel13.initial_transmission_sf_io = + absSF - sf_mod_period; + + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Program TX Request + TX_req = + &eNB->TX_req[CC_id]. + tx_request_body.tx_pdu_list[eNB->TX_req[CC_id]. + tx_request_body.number_of_pdus]; + TX_req->pdu_length = bcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = + bcch_sdu_length; + TX_req->segments[0].segment_data = + cc->BCCH_BR_pdu[i + 1].payload; + eNB->TX_req[CC_id].tx_request_body. + number_of_pdus++; + + if (opt_enabled == 1) { + trace_pdu(1, + &cc->BCCH_BR_pdu[i + 1].payload[0], + bcch_sdu_length, + 0xffff, + 4, + 0xffff, eNB->frame, eNB->subframe, 0, + 0); + LOG_D(OPT, + "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, + bcch_sdu_length); + } + if (cc->tdd_Config != NULL) { //TDD + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (TDD) for CC_id %d SI-BR %d bytes\n", + frameP, i, CC_id, bcch_sdu_length); + } else { + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (FDD) for CC_id %d SI-BR %d bytes\n", + frameP, i, CC_id, bcch_sdu_length); + } + } + } // scheduling in current frame/subframe + } //for SI List + } // eMTC is activated + } // CC_id + return; } #endif -void schedule_mib(module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP) { - - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - int mib_sdu_length; - int CC_id; - nfapi_dl_config_request_body_t *dl_req; - - AssertFatal(subframeP==0,"Subframe must be 0\n"); - AssertFatal((frameP&3)==0,"Frame must be a multiple of 4\n"); - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - cc = &eNB->common_channels[CC_id]; - - mib_sdu_length = mac_rrc_data_req(module_idP, - CC_id, - frameP, - MIBCH,1, - &cc->MIB_pdu.payload[0], - 1, - module_idP, - 0); // not used in this case - - LOG_D(MAC,"Frame %d, subframe %d: BCH PDU length %d\n", - frameP,subframeP,mib_sdu_length); - - if (mib_sdu_length > 0) { - - LOG_D(MAC,"Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", - frameP,subframeP,dl_req->number_pdu,mib_sdu_length); - - if ((frameP&1023) < 40) LOG_D(MAC,"[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n",module_idP,frameP,CC_id,mib_sdu_length,(int)cc->mib->message.schedulingInfoSIB1_BR_r13); - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE, - dl_config_pdu->pdu_size = 2+sizeof(nfapi_dl_config_bch_pdu); - dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length; - dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; - dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000; - dl_req->number_pdu++; - - LOG_D(MAC,"eNB->DL_req[0].number_pdu %d (%p)\n", - dl_req->number_pdu,&dl_req->number_pdu); - // DL request - - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = 3; - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = 0; - TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; +void +schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) +{ + + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + int mib_sdu_length; + int CC_id; + nfapi_dl_config_request_body_t *dl_req; + + AssertFatal(subframeP == 0, "Subframe must be 0\n"); + AssertFatal((frameP & 3) == 0, "Frame must be a multiple of 4\n"); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + cc = &eNB->common_channels[CC_id]; + + mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0], 1, module_idP, 0); // not used in this case + + LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", + frameP, subframeP, mib_sdu_length); + + if (mib_sdu_length > 0) { + + LOG_D(MAC, + "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", + frameP, subframeP, dl_req->number_pdu, mib_sdu_length); + + if ((frameP & 1023) < 40) + LOG_D(MAC, + "[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n", + module_idP, frameP, CC_id, mib_sdu_length, + (int) cc->mib->message.schedulingInfoSIB1_BR_r13); + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = + NFAPI_DL_CONFIG_BCH_PDU_TYPE, dl_config_pdu->pdu_size = + 2 + sizeof(nfapi_dl_config_bch_pdu); + dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length; + dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = + eNB->pdu_index[CC_id]; + dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000; + dl_req->number_pdu++; + + LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", + dl_req->number_pdu, &dl_req->number_pdu); + // DL request + + TX_req = + &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req + [CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = 3; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 0; + TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + } } - } } //------------------------------------------------------------------------------ void -schedule_SI( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP) - +schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int8_t bcch_sdu_length; - int mcs = -1; - int CC_id; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc; - uint8_t *vrb_map; - int first_rb = -1; - int N_RB_DL; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - nfapi_tx_request_pdu_t *TX_req; - nfapi_dl_config_request_body_t *dl_req; - - start_meas(&eNB->schedule_si); - - // Only schedule LTE System Information in subframe 5 - if (subframeP == 5) { - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - cc = &eNB->common_channels[CC_id]; - vrb_map = (void*)&cc->vrb_map; - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - - - bcch_sdu_length = mac_rrc_data_req(module_idP, - CC_id, - frameP, - BCCH,1, - &cc->BCCH_pdu.payload[0], - 1, - module_idP, - 0); // not used in this case - - if (bcch_sdu_length > 0) { - LOG_D(MAC,"[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n",module_idP,frameP,CC_id,bcch_sdu_length); - - // Allocate 4 PRBs in a random location - /* - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); - if ((vrb_map[first_rb] != 1) && - (vrb_map[first_rb+1] != 1) && - (vrb_map[first_rb+2] != 1) && - (vrb_map[first_rb+3] != 1)) - break; - } - */ - switch (N_RB_DL) { - case 6: - first_rb = 0; - break; - case 15: - first_rb = 6; - break; - case 25: - first_rb = 11; - break; - case 50: - first_rb = 23; - break; - case 100: - first_rb = 48; - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - // Get MCS for length of SI, 3 PRBs - if (bcch_sdu_length <= 7) { - mcs=0; - } else if (bcch_sdu_length <= 11) { - mcs=1; - } else if (bcch_sdu_length <= 18) { - mcs=2; - } else if (bcch_sdu_length <= 22) { - mcs=3; - } else if (bcch_sdu_length <= 26) { - mcs=4; - } else if (bcch_sdu_length <= 28) { - mcs=5; - } else if (bcch_sdu_length <= 32) { - mcs=6; - } else if (bcch_sdu_length <= 41) { - mcs=7; - } else if (bcch_sdu_length <= 49) { - mcs=8; - } - - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); + int8_t bcch_sdu_length; + int mcs = -1; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int first_rb = -1; + int N_RB_DL; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; + + start_meas(&eNB->schedule_si); + + // Only schedule LTE System Information in subframe 5 + if (subframeP == 5) { + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + cc = &eNB->common_channels[CC_id]; + vrb_map = (void *) &cc->vrb_map; + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + + bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH, 1, &cc->BCCH_pdu.payload[0], 1, module_idP, 0); // not used in this case + + if (bcch_sdu_length > 0) { + LOG_D(MAC, + "[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n", + module_idP, frameP, CC_id, bcch_sdu_length); + + // Allocate 4 PRBs in a random location + /* + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); + if ((vrb_map[first_rb] != 1) && + (vrb_map[first_rb+1] != 1) && + (vrb_map[first_rb+2] != 1) && + (vrb_map[first_rb+3] != 1)) + break; + } + */ + switch (N_RB_DL) { + case 6: + first_rb = 0; + break; + case 15: + first_rb = 6; + break; + case 25: + first_rb = 11; + break; + case 50: + first_rb = 23; + break; + case 100: + first_rb = 48; + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb + 1] = 1; + vrb_map[first_rb + 2] = 1; + vrb_map[first_rb + 3] = 1; + + // Get MCS for length of SI, 3 PRBs + if (bcch_sdu_length <= 7) { + mcs = 0; + } else if (bcch_sdu_length <= 11) { + mcs = 1; + } else if (bcch_sdu_length <= 18) { + mcs = 2; + } else if (bcch_sdu_length <= 22) { + mcs = 3; + } else if (bcch_sdu_length <= 26) { + mcs = 4; + } else if (bcch_sdu_length <= 28) { + mcs = 5; + } else if (bcch_sdu_length <= 32) { + mcs = 6; + } else if (bcch_sdu_length <= 41) { + mcs = 7; + } else if (bcch_sdu_length <= 49) { + mcs = 8; + } + + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = + NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + new_data_indicator_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + redundancy_version_1 = 0; + + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_block_coding = + getRIV(N_RB_DL, first_rb, 4); + + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 0; // regular UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF + + if (!CCE_allocation_infeasible + (module_idP, CC_id, 0, subframeP, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) { + LOG_D(MAC, + "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", + frameP, subframeP); + dl_req->number_dci++; + dl_req->number_pdu++; + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = + NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = + eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.resource_block_coding = + getRIV(N_RB_DL, first_rb, 4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag + = 0; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transmission_scheme = + (cc->p_eNB == 1) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + transmission_mode = (cc->p_eNB == 1) ? 1 : 2; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = + 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Program TX Request + TX_req = + &eNB->TX_req[CC_id]. + tx_request_body.tx_pdu_list[eNB->TX_req[CC_id]. + tx_request_body.number_of_pdus]; + TX_req->pdu_length = bcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = bcch_sdu_length; + TX_req->segments[0].segment_data = + cc->BCCH_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + + } else { + LOG_E(MAC, + "[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n", + module_idP, CC_id, frameP, subframeP); + } + + if (opt_enabled == 1) { + trace_pdu(1, + &cc->BCCH_pdu.payload[0], + bcch_sdu_length, + 0xffff, + 4, 0xffff, eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, + bcch_sdu_length); + } + if (cc->tdd_Config != NULL) { //TDD + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", + frameP, CC_id, bcch_sdu_length, mcs); + } else { + LOG_D(MAC, + "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", + frameP, CC_id, bcch_sdu_length, mcs); + } + + + eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1; + eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length; + eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length; + eNB->eNB_stats[CC_id].bcch_mcs = mcs; + } else { - // Rel10 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; - // Rel13 fields - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 0; // regular UE - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF - - if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,SI_RNTI)) { - LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", - frameP,subframeP); - dl_req->number_dci++; - dl_req->number_pdu++; - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - dl_req->number_pdu++; - - // Program TX Request - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = bcch_sdu_length; - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = bcch_sdu_length; - TX_req->segments[0].segment_data = cc->BCCH_pdu.payload; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; - - } - else { - LOG_E(MAC,"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n",module_idP, CC_id,frameP,subframeP); - } - - if (opt_enabled == 1) { - trace_pdu(1, - &cc->BCCH_pdu.payload[0], - bcch_sdu_length, - 0xffff, - 4, - 0xffff, - eNB->frame, - eNB->subframe, - 0, - 0); - LOG_D(OPT,"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", - module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); - } - if (cc->tdd_Config!=NULL) { //TDD - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", - frameP, - CC_id, - bcch_sdu_length, - mcs); - } else { - LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", - frameP, - CC_id, - bcch_sdu_length, - mcs); + //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); + } } - - - eNB->eNB_stats[CC_id].total_num_bcch_pdu+=1; - eNB->eNB_stats[CC_id].bcch_buffer=bcch_sdu_length; - eNB->eNB_stats[CC_id].total_bcch_buffer+=bcch_sdu_length; - eNB->eNB_stats[CC_id].bcch_mcs=mcs; - } else { - - //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); - } } - } - #ifdef Rel14 - schedule_SIB1_BR(module_idP,frameP,subframeP); - schedule_SI_BR(module_idP,frameP,subframeP); + schedule_SIB1_BR(module_idP, frameP, subframeP); + schedule_SI_BR(module_idP, frameP, subframeP); #endif - stop_meas(&eNB->schedule_si); - return; + stop_meas(&eNB->schedule_si); + return; } - diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 3e767ec516b076fa8d21d49dfca9f8f32708e1c6..9dbbb39d0346c563e9acbf208ca114ad3bb49570 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -51,10 +51,10 @@ //#include "LAYER2/MAC/pre_processor.c" #include "pdcp.h" -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #include "T.h" @@ -66,347 +66,346 @@ extern RAN_CONTEXT_t RC; //------------------------------------------------------------------------------ void -add_ue_dlsch_info( - module_id_t module_idP, - int CC_id, - int UE_id, - sub_frame_t subframeP, - UE_DLSCH_STATUS status -) +add_ue_dlsch_info(module_id_t module_idP, + int CC_id, + int UE_id, sub_frame_t subframeP, UE_DLSCH_STATUS status) //------------------------------------------------------------------------------ { - eNB_dlsch_info[module_idP][CC_id][UE_id].rnti = UE_RNTI(module_idP,UE_id); - // eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight = weight; - eNB_dlsch_info[module_idP][CC_id][UE_id].subframe = subframeP; - eNB_dlsch_info[module_idP][CC_id][UE_id].status = status; + eNB_dlsch_info[module_idP][CC_id][UE_id].rnti = + UE_RNTI(module_idP, UE_id); + // eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight = weight; + eNB_dlsch_info[module_idP][CC_id][UE_id].subframe = subframeP; + eNB_dlsch_info[module_idP][CC_id][UE_id].status = status; - eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++; + eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++; } //------------------------------------------------------------------------------ int -schedule_next_dlue( - module_id_t module_idP, - int CC_id, - sub_frame_t subframeP -) +schedule_next_dlue(module_id_t module_idP, int CC_id, + sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int next_ue; - UE_list_t *UE_list=&RC.mac[module_idP]->UE_list; + int next_ue; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) { - return next_ue; + for (next_ue = UE_list->head; next_ue >= 0; + next_ue = UE_list->next[next_ue]) { + if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == + S_DL_WAITING) { + return next_ue; + } } - } - for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_BUFFERED) { - eNB_dlsch_info[module_idP][CC_id][next_ue].status = S_DL_WAITING; + for (next_ue = UE_list->head; next_ue >= 0; + next_ue = UE_list->next[next_ue]) { + if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == + S_DL_BUFFERED) { + eNB_dlsch_info[module_idP][CC_id][next_ue].status = + S_DL_WAITING; + } } - } - return(-1);//next_ue; + return (-1); //next_ue; } //------------------------------------------------------------------------------ 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, - unsigned short timing_advance_cmd, - unsigned char *ue_cont_res_id, - unsigned char short_padding, - unsigned short post_padding -) +generate_dlsch_header(unsigned char *mac_header, + unsigned char num_sdus, + unsigned short *sdu_lengths, + unsigned char *sdu_lcids, + unsigned char drx_cmd, + unsigned 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; - uint8_t first_element=0,last_size=0,i; - uint8_t 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; + SCH_SUBHEADER_FIXED *mac_header_ptr = + (SCH_SUBHEADER_FIXED *) mac_header; + uint8_t first_element = 0, last_size = 0, i; + uint8_t 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; } - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = DRX_CMD; - 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 (timing_advance_cmd != 31) { - if (first_element>0) { - mac_header_ptr->E = 1; - mac_header_ptr++; - } else { - first_element=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; } - 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; - AssertFatal(timing_advance_cmd < 64,"timing_advance_cmd %d > 63\n",timing_advance_cmd); - ((TIMING_ADVANCE_CMD *)ce_ptr)->TA=timing_advance_cmd;//(timing_advance_cmd+31)&0x3f; - LOG_D(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; + if (timing_advance_cmd != 31) { + 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; + AssertFatal(timing_advance_cmd < 64, + "timing_advance_cmd %d > 63\n", timing_advance_cmd); + ((TIMING_ADVANCE_CMD *) ce_ptr)->TA = timing_advance_cmd; //(timing_advance_cmd+31)&0x3f; + LOG_D(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); } - 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; i<num_sdus; i++) { - LOG_T(MAC,"[eNB] Generate DLSCH header num sdu %d len sdu %d\n",num_sdus, sdu_lengths[i]); - - if (first_element>0) { - 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 (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; i < num_sdus; i++) { + LOG_T(MAC, "[eNB] Generate DLSCH header num sdu %d len sdu %d\n", + num_sdus, sdu_lengths[i]); + + if (first_element > 0) { + 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; + 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); + 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); + /* + + 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",(uint8_t*)mac_header_ptr - mac_header); - 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 ((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); } - */ - 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",(uint8_t*)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",(uint8_t*)mac_header_ptr - mac_header); - - return((unsigned char*)mac_header_ptr - mac_header); + //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header); + + return ((unsigned char *) mac_header_ptr - mac_header); } //------------------------------------------------------------------------------ void -set_ul_DAI( - int module_idP, - int UE_idP, - int CC_idP, - int frameP, - int subframeP -) +set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP, + int subframeP) //------------------------------------------------------------------------------ { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - unsigned char DAI; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - if (cc->tdd_Config != NULL) { //TDD - DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI-1)&3; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n",module_idP,CC_idP,frameP,subframeP,DAI,UE_idP); - // Save DAI for Format 0 DCI - - switch (cc->tdd_Config->subframeAssignment) { - case 0: - // if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6)) - break; - - case 1: - switch (subframeP) { - case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; - break; - - case 4: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; - break; - - case 6: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; - break; - - case 9: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; - break; - } - - case 2: - // if ((subframeP==3)||(subframeP==8)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; - break; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; + unsigned char DAI; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; + if (cc->tdd_Config != NULL) { //TDD + DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI - 1) & 3; + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n", + module_idP, CC_idP, frameP, subframeP, DAI, UE_idP); + // Save DAI for Format 0 DCI + + switch (cc->tdd_Config->subframeAssignment) { + case 0: + // if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6)) + break; + + case 1: + switch (subframeP) { + case 1: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; + break; + + case 4: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; + break; + + case 6: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + break; + + case 9: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + break; + } - case 3: + case 2: + // if ((subframeP==3)||(subframeP==8)) + // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + break; + + case 3: + + //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) { + // LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1); + // UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; + //} + switch (subframeP) { + case 5: + case 6: + case 1: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + break; + + case 7: + case 8: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + break; + + case 9: + case 0: + UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; + break; + + default: + break; + } - //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) { - // LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1); - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; - //} - switch (subframeP) { - case 5: - case 6: - case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; - break; - - case 7: - case 8: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; - break; - - case 9: - case 0: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; - break; - - default: - break; - } - - break; + break; - case 4: - // if ((subframeP==8)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; - break; + case 4: + // if ((subframeP==8)||(subframeP==9)) + // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + break; - case 5: - // if (subframeP==8) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; - break; + case 5: + // if (subframeP==8) + // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + break; - case 6: - // if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; - break; + case 6: + // if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9)) + // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + break; - default: - break; + default: + break; + } } - } } @@ -414,1130 +413,1342 @@ set_ul_DAI( //------------------------------------------------------------------------------ void -schedule_ue_spec( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - int* mbsfn_flag -) +schedule_ue_spec(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) //------------------------------------------------------------------------------ { - uint8_t CC_id; - int UE_id; - unsigned char aggregation; - mac_rlc_status_resp_t rlc_status; - unsigned char header_len_dcch=0, header_len_dcch_tmp=0; - unsigned char header_len_dtch=0, header_len_dtch_tmp=0, header_len_dtch_last=0; - unsigned char ta_len=0; - unsigned char sdu_lcids[NB_RB_MAX],lcid,offset,num_sdus=0; - uint16_t nb_rb,nb_rb_temp,nb_available_rb; - uint16_t TBS,j,sdu_lengths[NB_RB_MAX],rnti,padding=0,post_padding=0; - unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; - unsigned char round = 0; - unsigned char harq_pid = 0; - eNB_UE_STATS *eNB_UE_stats = NULL; - uint16_t sdu_length_total = 0; - - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; - int continue_flag=0; - int32_t normalized_rx_power, target_rx_power; - int32_t tpc=1; - static int32_t tpc_accumulated=0; - UE_sched_ctrl *ue_sched_ctl; - int mcs; - int i; - int min_rb_unit[MAX_NUM_CCs]; - int N_RB_DL[MAX_NUM_CCs]; - int total_nb_available_rb[MAX_NUM_CCs]; - int N_RBG[MAX_NUM_CCs]; - nfapi_dl_config_request_body_t *dl_req; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - int tdd_sfa; - int ta_update; + uint8_t CC_id; + int UE_id; + unsigned char aggregation; + mac_rlc_status_resp_t rlc_status; + unsigned char header_len_dcch = 0, header_len_dcch_tmp = 0; + unsigned char header_len_dtch = 0, header_len_dtch_tmp = + 0, header_len_dtch_last = 0; + unsigned char ta_len = 0; + unsigned char sdu_lcids[NB_RB_MAX], lcid, offset, num_sdus = 0; + uint16_t nb_rb, nb_rb_temp, nb_available_rb; + uint16_t TBS, j, sdu_lengths[NB_RB_MAX], rnti, padding = + 0, post_padding = 0; + unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; + unsigned char round = 0; + unsigned char harq_pid = 0; + eNB_UE_STATS *eNB_UE_stats = NULL; + uint16_t sdu_length_total = 0; + + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = eNB->common_channels; + UE_list_t *UE_list = &eNB->UE_list; + int continue_flag = 0; + int32_t normalized_rx_power, target_rx_power; + int32_t tpc = 1; + static int32_t tpc_accumulated = 0; + UE_sched_ctrl *ue_sched_ctl; + int mcs; + int i; + int min_rb_unit[MAX_NUM_CCs]; + int N_RB_DL[MAX_NUM_CCs]; + int total_nb_available_rb[MAX_NUM_CCs]; + int N_RBG[MAX_NUM_CCs]; + nfapi_dl_config_request_body_t *dl_req; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + int tdd_sfa; + int ta_update; #if 0 - if (UE_list->head==-1) { - return; - } + if (UE_list->head == -1) { + return; + } #endif - start_meas(&eNB->schedule_dlsch); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN); + start_meas(&eNB->schedule_dlsch); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); + + + // for TDD: check that we have to act here, otherwise return + if (cc[0].tdd_Config) { + tdd_sfa = cc[0].tdd_Config->subframeAssignment; + switch (subframeP) { + case 0: + // always continue + break; + case 1: + return; + break; + case 2: + return; + break; + case 3: + if ((tdd_sfa != 2) && (tdd_sfa != 5)) + return; + break; + case 4: + if ((tdd_sfa != 1) && (tdd_sfa != 2) && (tdd_sfa != 4) + && (tdd_sfa != 5)) + return; + break; + case 5: + break; + case 6: + case 7: + if ((tdd_sfa != 1) && (tdd_sfa != 2) && (tdd_sfa != 4) + && (tdd_sfa != 5)) + return; + break; + case 8: + if ((tdd_sfa != 2) && (tdd_sfa != 3) && (tdd_sfa != 4) + && (tdd_sfa != 5)) + return; + break; + case 9: + if ((tdd_sfa != 1) && (tdd_sfa != 3) && (tdd_sfa != 4) + && (tdd_sfa != 6)) + return; + break; - - // for TDD: check that we have to act here, otherwise return - if (cc[0].tdd_Config) { - tdd_sfa = cc[0].tdd_Config->subframeAssignment; - switch (subframeP) { - case 0: - // always continue - break; - case 1: - return; - break; - case 2: - return; - break; - case 3: - if ((tdd_sfa!=2) && (tdd_sfa!=5)) return; - break; - case 4: - if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return; - break; - case 5: - break; - case 6: - case 7: - if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return; - break; - case 8: - if ((tdd_sfa!=2)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return; - break; - case 9: - if ((tdd_sfa!=1)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=6)) return; - break; - + } + } + //weight = get_ue_weight(module_idP,UE_id); + aggregation = 2; + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth); + min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); + // get number of PRBs less those used by common channels + total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; + for (i = 0; i < N_RB_DL[CC_id]; i++) + if (cc[CC_id].vrb_map[i] != 0) + total_nb_available_rb[CC_id]--; + + N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth); + + // store the global enb stats: + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].available_prbs = + total_nb_available_rb[CC_id]; + eNB->eNB_stats[CC_id].total_available_prbs += + total_nb_available_rb[CC_id]; + eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; + eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; } - } - - //weight = get_ue_weight(module_idP,UE_id); - aggregation = 2; - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth); - min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id); - // get number of PRBs less those used by common channels - total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; - for (i=0;i<N_RB_DL[CC_id];i++) - if (cc[CC_id].vrb_map[i]!=0) - total_nb_available_rb[CC_id]--; - - N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth); - - // store the global enb stats: - eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; - eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; - eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; - } - - /// CALLING Pre_Processor for downlink scheduling (Returns estimation of RBs required by each UE and the allocation on sub-band) - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN); - start_meas(&eNB->schedule_dlsch_preprocessor); - dlsch_scheduler_pre_processor(module_idP, - frameP, - subframeP, - N_RBG, - mbsfn_flag); - stop_meas(&eNB->schedule_dlsch_preprocessor); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT); - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id); - - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - - if (mbsfn_flag[CC_id]>0) - continue; - - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - continue_flag=0; // reset the flag to allow allocation for the remaining UEs - rnti = UE_RNTI(module_idP,UE_id); - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - - if (rnti==NOT_A_RNTI) { - LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs); - continue_flag=1; - } - - if (eNB_UE_stats==NULL) { - LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n"); - continue_flag=1; - } - - if (continue_flag != 1){ - switch(get_tmode(module_idP,CC_id,UE_id)){ - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + + /// CALLING Pre_Processor for downlink scheduling (Returns estimation of RBs required by each UE and the allocation on sub-band) + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); + start_meas(&eNB->schedule_dlsch_preprocessor); + dlsch_scheduler_pre_processor(module_idP, + frameP, subframeP, N_RBG, mbsfn_flag); + stop_meas(&eNB->schedule_dlsch_preprocessor); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id); + + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + + if (mbsfn_flag[CC_id] > 0) + continue; + + for (UE_id = UE_list->head; UE_id >= 0; + UE_id = UE_list->next[UE_id]) { + continue_flag = 0; // reset the flag to allow allocation for the remaining UEs + rnti = UE_RNTI(module_idP, UE_id); + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + + + if (rnti == NOT_A_RNTI) { + LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", + UE_id, UE_list->num_UEs); + continue_flag = 1; + } + + if (eNB_UE_stats == NULL) { + LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); + continue_flag = 1; + } + + if (continue_flag != 1) { + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + aggregation = + get_aggregation(get_bw_index(module_idP, CC_id), ue_sched_ctl->dl_cqi[CC_id], format1); - break; - case 3: - aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + break; + case 3: + aggregation = + get_aggregation(get_bw_index(module_idP, CC_id), ue_sched_ctl->dl_cqi[CC_id], format2A); - break; - default: - LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id)); - aggregation = 2; - } - } /* if (continue_flag != 1 */ - - if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated - CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,aggregation,rnti) - ) { - LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, frameP, UE_id, CC_id); - continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5 - } - - if (cc[CC_id].tdd_Config != NULL) { //TDD - set_ue_dai (subframeP, - UE_id, - CC_id, - cc[CC_id].tdd_Config->subframeAssignment, - UE_list); - // update UL DAI after DLSCH scheduling - set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); - } - - if (continue_flag == 1 ) { - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_NONE); - continue; - } + break; + default: + LOG_W(MAC, "Unsupported transmission mode %d\n", + get_tmode(module_idP, CC_id, UE_id)); + aggregation = 2; + } + } + /* if (continue_flag != 1 */ + if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated + CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, + aggregation, rnti)) { + LOG_D(MAC, + "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", + module_idP, frameP, UE_id, CC_id); + continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 + } + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai(subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP, UE_id, CC_id, frameP, subframeP); + } + + if (continue_flag == 1) { + add_ue_dlsch_info(module_idP, + CC_id, UE_id, subframeP, S_DL_NONE); + continue; + } #warning RK->CR This old API call has to be revisited for FAPI, or logic must be changed #if 0 - /* add "fake" DCI to have CCE_allocation_infeasible work properly for next allocations */ - /* if we don't add it, next allocations may succeed but overall allocations may fail */ - /* will be removed at the end of this function */ - add_ue_spec_dci(&eNB->common_channels[CC_id].DCI_pdu, - &(char[]){0}, - rnti, - 1, - aggregation, - 1, - format1, - 0); + /* add "fake" DCI to have CCE_allocation_infeasible work properly for next allocations */ + /* if we don't add it, next allocations may succeed but overall allocations may fail */ + /* will be removed at the end of this function */ + add_ue_spec_dci(&eNB->common_channels[CC_id].DCI_pdu, &(char[]) { + 0}, rnti, 1, aggregation, 1, format1, 0); #endif - nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; + nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; - if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; - else harq_pid = ((frameP*10)+subframeP)&7; - - round = ue_sched_ctl->round[CC_id][harq_pid]; - - UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti; - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(module_idP,rnti); - UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; - UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; - - - if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED) continue; - - sdu_length_total=0; - num_sdus=0; - - /* - DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), - eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); - */ - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]]; - eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;//cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - - - // store stats - //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; - - // initializing the rb allocation indicator for each UE - for(j=0; j<N_RBG[CC_id]; j++) { - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; - } - - LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", - module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb, - ue_sched_ctl->dl_cqi[CC_id], eNB_UE_stats->dlsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); - - - - /* process retransmission */ - - if (round != 8) { - - // get freq_allocation - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - TBS = get_TBS_DL(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid],nb_rb); - - if (nb_rb <= nb_available_rb) { - if (cc[CC_id].tdd_Config != NULL) { - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI); - LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); - } - - if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { - for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) { - if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - if (UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]) printf("WARN: rballoc_subband not free for retrans?\n"); - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - - if((j == N_RBG[CC_id]-1) && - ((N_RB_DL[CC_id] == 25)|| - (N_RB_DL[CC_id] == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; - } - } - - j = j+1; - } - } - - nb_available_rb -= nb_rb; - /* - eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; - eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; - - for(j=0; j<N_RBG[CC_id]; j++) { - eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; - } - */ - - switch (get_tmode(module_idP,CC_id,UE_id)) { - case 1: - case 2: - case 7: - default: - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP,CC_id),ue_sched_ctl->dl_cqi[CC_id],format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round&3; - - if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", - module_idP,CC_id,harq_pid,round, - (UE_list->UE_template[CC_id][UE_id].DAI-1), - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]); - } else { - LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", - module_idP,CC_id,harq_pid,round, - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]); - - } - if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - - fill_nfapi_dlsch_config(eNB,dl_req, - TBS, - -1 /* retransmission, no pdu_index */, - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), - round&3 , // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0 // number of beamforming vectors, not used here - ); - - LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n",eNB->pdu_index[CC_id],round); - - program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // No TX request for retransmission (check if null request for FAPI) - } - else { - LOG_W(MAC,"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", - frameP,subframeP,UE_id,rnti); + if (cc->tdd_Config) + harq_pid = ((frameP * 10) + subframeP) % 10; + else + harq_pid = ((frameP * 10) + subframeP) & 7; + + round = ue_sched_ctl->round[CC_id][harq_pid]; + + UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti; + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = + mac_eNB_get_rrc_status(module_idP, rnti); + UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; + UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; + + + if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < + RRC_CONNECTED) + continue; + + sdu_length_total = 0; + num_sdus = 0; + + /* + DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), + eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); + */ + eNB_UE_stats->dlsch_mcs1 = + cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]]; + eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1; //cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + + + // store stats + //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; + + // initializing the rb allocation indicator for each UE + for (j = 0; j < N_RBG[CC_id]; j++) { + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] + = 0; } - } - - - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED); - - //eNB_UE_stats->dlsch_trials[round]++; - UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1; - } else { - LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", - module_idP, frameP, CC_id, UE_id); - } - } else { /* This is a potentially new SDU opportunity */ - - rlc_status.bytes_in_buffer = 0; - // Now check RLC information to compute number of required RBs - // get maximum TBS size for RLC request - TBS = 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 - - if (ue_sched_ctl->ta_timer == 0) { - ta_update = ue_sched_ctl->ta_update; - /* if we send TA then set timer to not send it for a while */ - if (ta_update != 31) - ue_sched_ctl->ta_timer = 20; - /* reset ta_update */ - ue_sched_ctl->ta_update = 31; - } else { - ta_update = 31; - } - - ta_len = (ta_update != 31) ? 2 : 0; - - header_len_dcch = 2; // 2 bytes DCCH SDU subheader - - if ( TBS-ta_len-header_len_dcch > 0 ) { - rlc_status = mac_rlc_status_ind( - module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - (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 CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP,frameP,CC_id,TBS-header_len_dcch); - sdu_lengths[0] = mac_rlc_data_req( - module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS, //not used - (char *)&dlsch_buffer[0]); - - T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_INT(DCCH), T_INT(sdu_lengths[0])); - - LOG_D(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",module_idP,CC_id,sdu_lengths[0]); - sdu_length_total = sdu_lengths[0]; - sdu_lcids[0] = DCCH; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0]; - num_sdus = 1; + + LOG_D(MAC, + "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + module_idP, frameP, UE_id, CC_id, rnti, harq_pid, round, + nb_available_rb, ue_sched_ctl->dl_cqi[CC_id], + eNB_UE_stats->dlsch_mcs1, + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); + + + + /* process retransmission */ + + if (round != 8) { + + // get freq_allocation + nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + TBS = + get_TBS_DL(UE_list-> + UE_template[CC_id][UE_id].oldmcs1[harq_pid], + nb_rb); + + if (nb_rb <= nb_available_rb) { + if (cc[CC_id].tdd_Config != NULL) { + UE_list->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(module_idP, CC_id, rnti, + UE_list->UE_template[CC_id][UE_id]. + DAI); + LOG_D(MAC, + "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", + CC_id, subframeP, UE_id, + UE_list->UE_template[CC_id][UE_id].DAI); + } + + if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band + UE_list->UE_template[CC_id][UE_id]. + rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + + while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { + if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == + 1) { + if (UE_list-> + UE_template[CC_id] + [UE_id].rballoc_subband[harq_pid][j]) + printf + ("WARN: rballoc_subband not free for retrans?\n"); + UE_list-> + UE_template[CC_id] + [UE_id].rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + + if ((j == N_RBG[CC_id] - 1) && + ((N_RB_DL[CC_id] == 25) || + (N_RB_DL[CC_id] == 50))) { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id] + + 1; + } else { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id]; + } + } + + j = j + 1; + } + } + + nb_available_rb -= nb_rb; + /* + eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; + eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; + + for(j=0; j<N_RBG[CC_id]; j++) { + eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; + } + */ + + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + default: + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req-> + number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = + NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index + (module_idP, CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = + rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.new_data_indicator_1 = + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = + UE_list->UE_template[CC_id][UE_id]. + oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.redundancy_version_1 = + round & 3; + + if (cc[CC_id].tdd_Config != NULL) { //TDD + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.downlink_assignment_index = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + LOG_D(MAC, + "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", + module_idP, CC_id, harq_pid, round, + (UE_list->UE_template[CC_id][UE_id].DAI - + 1), + UE_list-> + UE_template[CC_id][UE_id].oldmcs1 + [harq_pid]); + } else { + LOG_D(MAC, + "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", + module_idP, CC_id, harq_pid, round, + UE_list-> + UE_template[CC_id][UE_id].oldmcs1 + [harq_pid]); + + } + if (!CCE_allocation_infeasible + (module_idP, CC_id, 1, subframeP, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + + fill_nfapi_dlsch_config(eNB, dl_req, TBS, -1 + /* retransmission, no pdu_index */ + , rnti, 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 3, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0 // number of beamforming vectors, not used here + ); + + LOG_D(MAC, + "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", + eNB->pdu_index[CC_id], round); + + program_dlsch_acknak(module_idP, CC_id, UE_id, + frameP, subframeP, + dl_config_pdu-> + dci_dl_pdu.dci_dl_pdu_rel8. + cce_idx); + // No TX request for retransmission (check if null request for FAPI) + } else { + LOG_W(MAC, + "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", + frameP, subframeP, UE_id, rnti); + } + } + + + add_ue_dlsch_info(module_idP, + CC_id, UE_id, subframeP, + S_DL_SCHEDULED); + + //eNB_UE_stats->dlsch_trials[round]++; + UE_list->eNB_UE_stats[CC_id][UE_id]. + num_retransmission += 1; + UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = + nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id]. + total_rbs_used_retx += nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = + eNB_UE_stats->dlsch_mcs1; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = + eNB_UE_stats->dlsch_mcs1; + } else { + LOG_D(MAC, + "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + module_idP, frameP, CC_id, UE_id); + } + } else { /* This is a potentially new SDU opportunity */ + + rlc_status.bytes_in_buffer = 0; + // Now check RLC information to compute number of required RBs + // get maximum TBS size for RLC request + TBS = + 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 + + if (ue_sched_ctl->ta_timer == 0) { + ta_update = ue_sched_ctl->ta_update; + /* if we send TA then set timer to not send it for a while */ + if (ta_update != 31) + ue_sched_ctl->ta_timer = 20; + /* reset ta_update */ + ue_sched_ctl->ta_update = 31; + } else { + ta_update = 31; + } + + ta_len = (ta_update != 31) ? 2 : 0; + + header_len_dcch = 2; // 2 bytes DCCH SDU subheader + + if (TBS - ta_len - header_len_dcch > 0) { + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, (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 CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + module_idP, frameP, CC_id, + TBS - header_len_dcch); + sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, TBS, //not used + (char *) + &dlsch_buffer + [0]); + + T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), + T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), T_INT(DCCH), + T_INT(sdu_lengths[0])); + + LOG_D(MAC, + "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", + module_idP, CC_id, sdu_lengths[0]); + sdu_length_total = sdu_lengths[0]; + sdu_lcids[0] = DCCH; + UE_list->eNB_UE_stats[CC_id][UE_id]. + num_pdu_tx[DCCH] += 1; + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] + += sdu_lengths[0]; + num_sdus = 1; #ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[0]); + LOG_T(MAC, + "[eNB %d][DCCH] CC_id %d Got %d bytes :", + module_idP, CC_id, sdu_lengths[0]); - for (j=0; j<sdu_lengths[0]; j++) { - LOG_T(MAC,"%x ",dlsch_buffer[j]); - } + for (j = 0; j < sdu_lengths[0]; j++) { + LOG_T(MAC, "%x ", dlsch_buffer[j]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - } else { - header_len_dcch = 0; - sdu_length_total = 0; - } - } - - // check for DCCH1 and update header information (assume 2 byte sub-header) - if (TBS-ta_len-header_len_dcch-sdu_length_total > 0 ) { - rlc_status = mac_rlc_status_ind( - module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH+1, - (TBS-ta_len-header_len_dcch-sdu_length_total)); // transport block set size less allocations for timing advance and - // DCCH SDU - sdu_lengths[num_sdus] = 0; - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total); - sdu_lengths[num_sdus] += mac_rlc_data_req( - module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH+1, - TBS, //not used - (char *)&dlsch_buffer[sdu_length_total]); - - T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_INT(DCCH+1), T_INT(sdu_lengths[num_sdus])); - - sdu_lcids[num_sdus] = DCCH1; - sdu_length_total += sdu_lengths[num_sdus]; - header_len_dcch += 2; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1]+=sdu_lengths[num_sdus]; - num_sdus++; + } else { + header_len_dcch = 0; + sdu_length_total = 0; + } + } + // check for DCCH1 and update header information (assume 2 byte sub-header) + if (TBS - ta_len - header_len_dcch - sdu_length_total > 0) { + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, (TBS - ta_len - header_len_dcch - sdu_length_total)); // transport block set size less allocations for timing advance and + // DCCH SDU + sdu_lengths[num_sdus] = 0; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, + "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + module_idP, frameP, CC_id, + TBS - header_len_dcch - sdu_length_total); + sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, TBS, //not used + (char *) + &dlsch_buffer + [sdu_length_total]); + + T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), + T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), + T_INT(DCCH + 1), T_INT(sdu_lengths[num_sdus])); + + sdu_lcids[num_sdus] = DCCH1; + sdu_length_total += sdu_lengths[num_sdus]; + header_len_dcch += 2; + UE_list->eNB_UE_stats[CC_id][UE_id]. + num_pdu_tx[DCCH1] += 1; + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] + += sdu_lengths[num_sdus]; + num_sdus++; #ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC,"[eNB %d][DCCH1] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[num_sdus]); + LOG_T(MAC, + "[eNB %d][DCCH1] CC_id %d Got %d bytes :", + module_idP, CC_id, sdu_lengths[num_sdus]); - for (j=0; j<sdu_lengths[num_sdus]; j++) { - LOG_T(MAC,"%x ",dlsch_buffer[j]); - } + for (j = 0; j < sdu_lengths[num_sdus]; j++) { + LOG_T(MAC, "%x ", dlsch_buffer[j]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - } - } - - // assume the max dtch header size, and adjust it later - header_len_dtch=0; - header_len_dtch_last=0; // the header length of the last mac sdu - // lcid has to be sorted before the actual allocation (similar struct as ue_list). - for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){ - // TBD: check if the lcid is active - - header_len_dtch+=3; - header_len_dtch_last=3; - LOG_D(MAC,"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", - module_idP,frameP,lcid,TBS, - TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); - - if (TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch > 0 ) { // NN: > 2 ? - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); - - - if (rlc_status.bytes_in_buffer > 0) { - - LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", - module_idP,frameP,TBS-header_len_dcch-sdu_length_total-header_len_dtch,lcid, header_len_dtch); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS, //not used - (char*)&dlsch_buffer[sdu_length_total]); - T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus])); - - LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",module_idP,sdu_lengths[num_sdus],lcid); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid]+=sdu_lengths[num_sdus]; - if (sdu_lengths[num_sdus] < 128) { - header_len_dtch--; - header_len_dtch_last--; - } - num_sdus++; - } // no data for this LCID - else { - header_len_dtch-=3; - } - } // no TBS left - else { - header_len_dtch-=3; - break; - } - } - if (header_len_dtch == 0 ) - header_len_dtch_last= 0; - // there is at least one SDU - // if (num_sdus > 0 ){ - 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 : 0;//header_len_dcch; // remove length field - } else { - header_len_dtch_last-=1; // now use it to find how many bytes has to be removed for the last MAC SDU - header_len_dtch = (header_len_dtch > 0) ? header_len_dtch - header_len_dtch_last :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[CC_id]; - } - - TBS = get_TBS_DL(mcs,nb_rb); - - while (TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) { - nb_rb += min_rb_unit[CC_id]; // - - 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 = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb); - } - - if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { - for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) { - if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - - if ((j == N_RBG[CC_id]-1) && - ((N_RB_DL[CC_id] == 25)|| - (N_RB_DL[CC_id] == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; - } - } - - j = j+1; - } - } - - // 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 = 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)) && ((( ue_sched_ctl->dl_pow_off[CC_id]>0) && (mcs<28)) - || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs<=15)))) { - mcs++; - TBS = 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); + } + } + // assume the max dtch header size, and adjust it later + header_len_dtch = 0; + header_len_dtch_last = 0; // the header length of the last mac sdu + // lcid has to be sorted before the actual allocation (similar struct as ue_list). + for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { + // TBD: check if the lcid is active + + header_len_dtch += 3; + header_len_dtch_last = 3; + LOG_D(MAC, + "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + module_idP, frameP, lcid, TBS, + TBS - ta_len - header_len_dcch - + sdu_length_total - header_len_dtch); + + if (TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch > 0) { // NN: > 2 ? + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS - ta_len - + header_len_dcch - + sdu_length_total - + header_len_dtch); + + + if (rlc_status.bytes_in_buffer > 0) { + + LOG_D(MAC, + "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", + module_idP, frameP, + TBS - header_len_dcch - + sdu_length_total - header_len_dtch, lcid, + header_len_dtch); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, TBS, //not used + (char + *) + &dlsch_buffer + [sdu_length_total]); + T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), + T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), + T_INT(lcid), T_INT(sdu_lengths[num_sdus])); + + LOG_D(MAC, + "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", + module_idP, sdu_lengths[num_sdus], lcid); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] + += 1; + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_bytes_tx + [lcid] += sdu_lengths[num_sdus]; + if (sdu_lengths[num_sdus] < 128) { + header_len_dtch--; + header_len_dtch_last--; + } + num_sdus++; + } // no data for this LCID + else { + header_len_dtch -= 3; + } + } // no TBS left + else { + header_len_dtch -= 3; + break; + } + } + if (header_len_dtch == 0) + header_len_dtch_last = 0; + // there is at least one SDU + // if (num_sdus > 0 ){ + 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 : 0; //header_len_dcch; // remove length field + } else { + header_len_dtch_last -= 1; // now use it to find how many bytes has to be removed for the last MAC SDU + header_len_dtch = (header_len_dtch > 0) ? header_len_dtch - header_len_dtch_last : 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[CC_id]; + } + + TBS = get_TBS_DL(mcs, nb_rb); + + while (TBS < + (sdu_length_total + header_len_dcch + + header_len_dtch + ta_len)) { + nb_rb += min_rb_unit[CC_id]; // + + 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 = + get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_available_rb); + nb_rb = nb_available_rb; + break; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rb); + } + + if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band + UE_list->UE_template[CC_id][UE_id]. + rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + + while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { + if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == + 1) { + UE_list-> + UE_template[CC_id] + [UE_id].rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + + if ((j == N_RBG[CC_id] - 1) && + ((N_RB_DL[CC_id] == 25) || + (N_RB_DL[CC_id] == 50))) { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id] + + 1; + } else { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id]; + } + } + + j = j + 1; + } + } + + // 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 = 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)) + && (((ue_sched_ctl->dl_pow_off[CC_id] > 0) + && (mcs < 28)) + || ((ue_sched_ctl->dl_pow_off[CC_id] == 0) + && (mcs <= 15)))) { + mcs++; + TBS = 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] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", - module_idP,CC_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); + LOG_D(MAC, + "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", + module_idP, CC_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*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); - - //#ifdef DEBUG_eNB_SCHEDULER - if (ta_update != 31) { - LOG_D(MAC, - "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n", - module_idP,frameP, UE_id, CC_id, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset, - ta_update,padding,post_padding,mcs,TBS,nb_rb,header_len_dcch,header_len_dtch); - } - //#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 *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, post_padding); + + //#ifdef DEBUG_eNB_SCHEDULER + if (ta_update != 31) { + LOG_D(MAC, + "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n", + module_idP, frameP, UE_id, CC_id, + sdu_length_total, num_sdus, sdu_lengths[0], + sdu_lcids[0], offset, ta_update, padding, + post_padding, mcs, TBS, nb_rb, + header_len_dcch, header_len_dtch); + } + //#endif #ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n"); + LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); - for (i=0; i<16; i++) { - LOG_T(MAC,"%x.",dlsch_buffer[i]); - } + for (i = 0; i < 16; i++) { + LOG_T(MAC, "%x.", dlsch_buffer[i]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - // cycle through SDUs and place in dlsch_buffer - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); - // memcpy(RC.mac[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++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); - } - - - if (opt_enabled == 1) { - trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - TBS, module_idP, 3, UE_RNTI(module_idP,UE_id), - eNB->frame, eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n", - module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), TBS); - } - - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); - - UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; - - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED); - // store stats - eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; - eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; - - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; - UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; - - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; - - if (cc[CC_id].tdd_Config != NULL) { // TDD - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI); - } - - // do PUCCH power control - // this is the normalized RX power - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - - /* TODO: fix how we deal with power, unit is not dBm, it's special from nfapi */ - normalized_rx_power = ue_sched_ctl->pucch1_snr[CC_id]; - target_rx_power = 208; - - // this assumes accumulated tpc - // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; - if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case - ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around - if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { - ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; - - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; - - if (normalized_rx_power>(target_rx_power+4)) { - tpc = 0; //-1 - tpc_accumulated--; - } else if (normalized_rx_power<(target_rx_power-4)) { - tpc = 2; //+1 - tpc_accumulated++; - } else { - tpc = 1; //0 - } - - LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", - module_idP,frameP, subframeP,harq_pid,tpc, - tpc_accumulated,normalized_rx_power,target_rx_power); - - } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 - } - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP,CC_id),ue_sched_ctl->dl_cqi[CC_id],format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - //deactivate second codeword - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; - if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", - module_idP,CC_id,harq_pid, - (UE_list->UE_template[CC_id][UE_id].DAI-1), - mcs); - } else { - LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", - module_idP,CC_id,harq_pid,mcs); - - } - LOG_D(MAC,"Checking feasibility pdu %d (new sdu)\n",dl_req->number_pdu); - if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,rnti)) { - - - ue_sched_ctl->round[CC_id][harq_pid] = 0; - dl_req->number_dci++; - dl_req->number_pdu++; - - // Toggle NDI for next time - LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, frameP,subframeP,UE_id, - rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - - fill_nfapi_dlsch_config(eNB,dl_req, - TBS, - eNB->pdu_index[CC_id], - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(mcs), - 0, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0 // number of beamforming vectors, not used here - ); - eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, - (frameP*10)+subframeP, - TBS, - eNB->pdu_index[CC_id], - eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); - - LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",eNB->pdu_index[CC_id]); - - eNB->pdu_index[CC_id]++; - program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - - } - else { - LOG_W(MAC,"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", - frameP,subframeP,UE_id,rnti); - } - } else { // There is no data from RLC or MAC header, so don't schedule - - } - } - - if (cc[CC_id].tdd_Config != NULL){ // TDD - set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); - } - - } // UE_id loop - } // CC_id loop - - - - fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_flag); - - stop_meas(&eNB->schedule_dlsch); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT); + // cycle through SDUs and place in dlsch_buffer + memcpy(&UE_list-> + DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], + dlsch_buffer, sdu_length_total); + // memcpy(RC.mac[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++) { + UE_list->DLSCH_pdu[CC_id][0][UE_id]. + payload[0][offset + sdu_length_total + j] = + (char) (taus() & 0xff); + } + + + if (opt_enabled == 1) { + trace_pdu(1, (uint8_t *) + UE_list->DLSCH_pdu[CC_id][0][UE_id]. + payload[0], TBS, module_idP, 3, + UE_RNTI(module_idP, UE_id), eNB->frame, + eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n", + module_idP, CC_id, frameP, + UE_RNTI(module_idP, UE_id), TBS); + } + + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), + T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), + T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id]. + payload[0], TBS)); + + UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = + nb_rb; + + add_ue_dlsch_info(module_idP, + CC_id, UE_id, subframeP, + S_DL_SCHEDULED); + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx += + sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; + + UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += + nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = + eNB_UE_stats->dlsch_mcs1; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = mcs; + UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; + + UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes = + TBS - sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes += + sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes += + TBS; + UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus += + 1; + + if (cc[CC_id].tdd_Config != NULL) { // TDD + UE_list->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(module_idP, CC_id, rnti, + UE_list->UE_template[CC_id][UE_id]. + DAI); + } + // do PUCCH power control + // this is the normalized RX power + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + + /* TODO: fix how we deal with power, unit is not dBm, it's special from nfapi */ + normalized_rx_power = ue_sched_ctl->pucch1_snr[CC_id]; + target_rx_power = 208; + + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = + UE_list->UE_template[CC_id][UE_id]. + pucch_tpc_tx_frame * 10 + + UE_list->UE_template[CC_id][UE_id]. + pucch_tpc_tx_subframe; + if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || //normal case + ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10)))) //frame wrap-around + if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { + ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; + + UE_list-> + UE_template[CC_id] + [UE_id].pucch_tpc_tx_frame = frameP; + UE_list-> + UE_template[CC_id] + [UE_id].pucch_tpc_tx_subframe = subframeP; + + if (normalized_rx_power > + (target_rx_power + 4)) { + tpc = 0; //-1 + tpc_accumulated--; + } else if (normalized_rx_power < + (target_rx_power - 4)) { + tpc = 2; //+1 + tpc_accumulated++; + } else { + tpc = 1; //0 + } + + LOG_D(MAC, + "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + module_idP, frameP, subframeP, harq_pid, + tpc, tpc_accumulated, + normalized_rx_power, target_rx_power); + + } // Po_PUCCH has been updated + else { + tpc = 1; //0 + } // time to do TPC update + else { + tpc = 1; //0 + } + + dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = + NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = + NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, CC_id), + ue_sched_ctl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.new_data_indicator_1 = + 1 - + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.redundancy_version_1 = 0; + //deactivate second codeword + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.redundancy_version_2 = 1; + if (cc[CC_id].tdd_Config != NULL) { //TDD + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.downlink_assignment_index = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + LOG_D(MAC, + "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", + module_idP, CC_id, harq_pid, + (UE_list->UE_template[CC_id][UE_id].DAI - 1), + mcs); + } else { + LOG_D(MAC, + "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", + module_idP, CC_id, harq_pid, mcs); + + } + LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", + dl_req->number_pdu); + if (!CCE_allocation_infeasible + (module_idP, CC_id, 1, subframeP, + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, rnti)) { + + + ue_sched_ctl->round[CC_id][harq_pid] = 0; + dl_req->number_dci++; + dl_req->number_pdu++; + + // Toggle NDI for next time + LOG_D(MAC, + "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, frameP, subframeP, UE_id, rnti, + harq_pid, + UE_list-> + UE_template[CC_id][UE_id].oldNDI[harq_pid]); + + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid] = + 1 - + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + UE_list->UE_template[CC_id][UE_id]. + oldmcs1[harq_pid] = mcs; + UE_list->UE_template[CC_id][UE_id]. + oldmcs2[harq_pid] = 0; + AssertFatal(UE_list->UE_template[CC_id] + [UE_id].physicalConfigDedicated != + NULL, + "physicalConfigDedicated is NULL\n"); + AssertFatal(UE_list->UE_template[CC_id] + [UE_id]. + physicalConfigDedicated->pdsch_ConfigDedicated + != NULL, + "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + + fill_nfapi_dlsch_config(eNB, dl_req, TBS, eNB->pdu_index[CC_id], rnti, 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(mcs), 0, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0 // number of beamforming vectors, not used here + ); + eNB->TX_req[CC_id].sfn_sf = + fill_nfapi_tx_req(&eNB-> + TX_req + [CC_id].tx_request_body, + (frameP * 10) + subframeP, + TBS, eNB->pdu_index[CC_id], + eNB-> + UE_list.DLSCH_pdu[CC_id][0][(unsigned char) + UE_id].payload + [0]); + + LOG_D(MAC, + "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", + eNB->pdu_index[CC_id]); + + eNB->pdu_index[CC_id]++; + program_dlsch_acknak(module_idP, CC_id, UE_id, + frameP, subframeP, + dl_config_pdu-> + dci_dl_pdu.dci_dl_pdu_rel8. + cce_idx); + + } else { + LOG_W(MAC, + "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", + frameP, subframeP, UE_id, rnti); + } + } else { // There is no data from RLC or MAC header, so don't schedule + + } + } + + if (cc[CC_id].tdd_Config != NULL) { // TDD + set_ul_DAI(module_idP, UE_id, CC_id, frameP, subframeP); + } + + } // UE_id loop + } // CC_id loop + + + + fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_flag); + + stop_meas(&eNB->schedule_dlsch); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT); } //------------------------------------------------------------------------------ void -fill_DLSCH_dci( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - int* mbsfn_flagP - ) +fill_DLSCH_dci(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP, int *mbsfn_flagP) //------------------------------------------------------------------------------ { - // loop over all allocated UEs and compute frequency allocations for PDSCH - int UE_id = -1; - uint8_t /* first_rb, */ nb_rb=3; - rnti_t rnti; - //unsigned char *vrb_map; - uint8_t rballoc_sub[25]; - //uint8_t number_of_subbands=13; - - //unsigned char round; - unsigned char harq_pid; - int i; - int CC_id; - eNB_MAC_INST *eNB =RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - int N_RBG; - int N_RB_DL; - COMMON_channels_t *cc; - - start_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI,VCD_FUNCTION_IN); - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - LOG_D(MAC,"Doing fill DCI for CC_id %d\n",CC_id); - - if (mbsfn_flagP[CC_id]>0) - continue; - - cc = &eNB->common_channels[CC_id]; - N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - - // UE specific DCIs - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - LOG_T(MAC,"CC_id %d, UE_id: %d => status %d\n",CC_id,UE_id,eNB_dlsch_info[module_idP][CC_id][UE_id].status); - - if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == S_DL_SCHEDULED) { - - // clear scheduling flag - eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING; - rnti = UE_RNTI(module_idP,UE_id); - if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; - else harq_pid = ((frameP*10)+subframeP)&7; - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - - - - /// Synchronizing rballoc with rballoc_sub - for(i=0; i<N_RBG; i++) { - rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; - } - - nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; - nfapi_dl_config_request_pdu_t* dl_config_pdu; - - for (i=0;i<DL_req[CC_id].dl_config_request_body.number_pdu;i++) { - dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[i]; - if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&& - (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti) && - (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1)) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb,N_RB_DL,N_RBG,rballoc_sub); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - } - else if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE)&& - (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti) && - (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type==0)) { - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb,N_RB_DL,N_RBG,rballoc_sub); - } + // loop over all allocated UEs and compute frequency allocations for PDSCH + int UE_id = -1; + uint8_t /* first_rb, */ nb_rb = 3; + rnti_t rnti; + //unsigned char *vrb_map; + uint8_t rballoc_sub[25]; + //uint8_t number_of_subbands=13; + + //unsigned char round; + unsigned char harq_pid; + int i; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; + int N_RBG; + int N_RB_DL; + COMMON_channels_t *cc; + + start_meas(&eNB->fill_DLSCH_dci); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + LOG_D(MAC, "Doing fill DCI for CC_id %d\n", CC_id); + + if (mbsfn_flagP[CC_id] > 0) + continue; + + cc = &eNB->common_channels[CC_id]; + N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); + N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + + // UE specific DCIs + for (UE_id = UE_list->head; UE_id >= 0; + UE_id = UE_list->next[UE_id]) { + LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, UE_id, + eNB_dlsch_info[module_idP][CC_id][UE_id].status); + + if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == + S_DL_SCHEDULED) { + + // clear scheduling flag + eNB_dlsch_info[module_idP][CC_id][UE_id].status = + S_DL_WAITING; + rnti = UE_RNTI(module_idP, UE_id); + if (cc->tdd_Config) + harq_pid = ((frameP * 10) + subframeP) % 10; + else + harq_pid = ((frameP * 10) + subframeP) & 7; + nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + + + + /// Synchronizing rballoc with rballoc_sub + for (i = 0; i < N_RBG; i++) { + rballoc_sub[i] = + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband[harq_pid] + [i]; + } + + nfapi_dl_config_request_t *DL_req = + &RC.mac[module_idP]->DL_req[0]; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + + for (i = 0; + i < DL_req[CC_id].dl_config_request_body.number_pdu; + i++) { + dl_config_pdu = + &DL_req[CC_id]. + dl_config_request_body.dl_config_pdu_list[i]; + if ((dl_config_pdu->pdu_type == + NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) + && (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + rnti == rnti) + && (dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.dci_format != 1)) { + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_block_coding = + allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, + rballoc_sub); + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.resource_allocation_type = 0; + } else + if ((dl_config_pdu->pdu_type == + NFAPI_DL_CONFIG_DLSCH_PDU_TYPE) + && (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8. + rnti == rnti) + && (dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.resource_allocation_type == + 0)) { + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.resource_block_coding = + allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, + rballoc_sub); + } + } + } } - } - } - } + } - stop_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI,VCD_FUNCTION_OUT); + stop_meas(&eNB->fill_DLSCH_dci); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_OUT); } //------------------------------------------------------------------------------ -unsigned char* -get_dlsch_sdu( - module_id_t module_idP, - int CC_id, - frame_t frameP, - rnti_t rntiP, - uint8_t TBindex -) +unsigned char *get_dlsch_sdu(module_id_t module_idP, + int CC_id, frame_t frameP, rnti_t rntiP, + uint8_t TBindex) //------------------------------------------------------------------------------ { - int UE_id; - eNB_MAC_INST *eNB=RC.mac[module_idP]; + int UE_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; - if (rntiP==SI_RNTI) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n", module_idP, CC_id, frameP); + if (rntiP == SI_RNTI) { + LOG_D(MAC, "[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n", + module_idP, CC_id, frameP); - return((unsigned char *)&eNB->common_channels[CC_id].BCCH_pdu.payload[0]); - } + return ((unsigned char *) &eNB->common_channels[CC_id]. + BCCH_pdu.payload[0]); + } - UE_id = find_UE_id(module_idP,rntiP); + UE_id = find_UE_id(module_idP, rntiP); - if (UE_id != -1) { - LOG_D(MAC,"[eNB %d] Frame %d: CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n",module_idP,frameP,CC_id,rntiP,UE_id); - return((unsigned char *)&eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); - } else { - LOG_E(MAC,"[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", module_idP,frameP,CC_id,rntiP); - return NULL; - } + if (UE_id != -1) { + LOG_D(MAC, + "[eNB %d] Frame %d: CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n", + module_idP, frameP, CC_id, rntiP, UE_id); + return ((unsigned char *) &eNB-> + UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); + } else { + LOG_E(MAC, + "[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", + module_idP, frameP, CC_id, rntiP); + return NULL; + } } //------------------------------------------------------------------------------ -void update_ul_dci(module_id_t module_idP, - uint8_t CC_idP, - rnti_t rntiP, - uint8_t daiP) +void +update_ul_dci(module_id_t module_idP, + uint8_t CC_idP, rnti_t rntiP, uint8_t daiP) //------------------------------------------------------------------------------ { - nfapi_hi_dci0_request_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP]; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[0]; - COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_idP]; - int i; + nfapi_hi_dci0_request_t *HI_DCI0_req = + &RC.mac[module_idP]->HI_DCI0_req[CC_idP]; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = + &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[0]; + COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_idP]; + int i; + + if (cc->tdd_Config != NULL) { // TDD + for (i = 0; + i < + HI_DCI0_req->hi_dci0_request_body.number_of_dci + + HI_DCI0_req->hi_dci0_request_body.number_of_dci; i++) { - if (cc->tdd_Config != NULL) { // TDD - for (i=0; i<HI_DCI0_req->hi_dci0_request_body.number_of_dci + HI_DCI0_req->hi_dci0_request_body.number_of_dci; i++) { + if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) && + (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP)) + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index = + (daiP - 1) & 3; - if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) && - (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP)) - hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index = (daiP-1)&3; - + } } - } } //------------------------------------------------------------------------------ -void set_ue_dai( - sub_frame_t subframeP, - int UE_id, - uint8_t CC_id, - uint8_t tdd_config, - UE_list_t* UE_list -) +void +set_ue_dai(sub_frame_t subframeP, + int UE_id, uint8_t CC_id, uint8_t tdd_config, + UE_list_t * UE_list) //------------------------------------------------------------------------------ { - switch (tdd_config) { - case 0: - if ((subframeP==0)||(subframeP==1)||(subframeP==3)||(subframeP==5)||(subframeP==6)||(subframeP==8)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + switch (tdd_config) { + case 0: + if ((subframeP == 0) || (subframeP == 1) || (subframeP == 3) + || (subframeP == 5) || (subframeP == 6) || (subframeP == 8)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 1: - if ((subframeP==0)||(subframeP==4)||(subframeP==5)||(subframeP==9)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 1: + if ((subframeP == 0) || (subframeP == 4) || (subframeP == 5) + || (subframeP == 9)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 2: - if ((subframeP==4)||(subframeP==5)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 2: + if ((subframeP == 4) || (subframeP == 5)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 3: - if ((subframeP==5)||(subframeP==7)||(subframeP==9)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 3: + if ((subframeP == 5) || (subframeP == 7) || (subframeP == 9)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 4: - if ((subframeP==0)||(subframeP==6)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 4: + if ((subframeP == 0) || (subframeP == 6)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 5: - if (subframeP==9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 5: + if (subframeP == 9) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - case 6: - if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6)||(subframeP==9)) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; - } + case 6: + if ((subframeP == 0) || (subframeP == 1) || (subframeP == 5) + || (subframeP == 6) || (subframeP == 9)) { + UE_list->UE_template[CC_id][UE_id].DAI = 0; + } - break; + break; - default: - UE_list->UE_template[CC_id][UE_id].DAI = 0; - LOG_N(MAC,"unknow TDD config %d\n",tdd_config); - break; - } + default: + UE_list->UE_template[CC_id][UE_id].DAI = 0; + LOG_N(MAC, "unknow TDD config %d\n", tdd_config); + break; + } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index 3b05850a1d58d851c609d9b22985208265360ff3..7ce5a5b12c3e4f737de710c27dada2c647ab5ced 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -52,10 +52,10 @@ #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 @@ -63,607 +63,746 @@ extern RAN_CONTEXT_t RC; #if defined(Rel10) || defined(Rel14) -int8_t get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t CC_id, uint8_t mbsfn_sync_area) +int8_t +get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, + uint8_t 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] CC_id %d MBSFN synchronization area %d out of range\n ", module_idP, CC_id, mbsfn_sync_area); - return -1; - } else if (RC.mac[module_idP]->common_channels[CC_id].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) { - return mbsfn_sync_area; - } else { - LOG_W(MAC,"[eNB %d] CC_id %d MBSFN Subframe Config pattern %d not found \n ", module_idP, CC_id, mbsfn_sync_area); - return -1; - } + // 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] CC_id %d MBSFN synchronization area %d out of range\n ", + module_idP, CC_id, mbsfn_sync_area); + return -1; + } else if (RC.mac[module_idP]-> + common_channels[CC_id].mbsfn_SubframeConfig[mbsfn_sync_area] + != NULL) { + return mbsfn_sync_area; + } else { + LOG_W(MAC, + "[eNB %d] CC_id %d MBSFN Subframe Config pattern %d not found \n ", + module_idP, CC_id, mbsfn_sync_area); + return -1; + } } -int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframeP) +int +schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + sub_frame_t subframeP) { - int mcch_flag=0,mtch_flag=0, msi_flag=0; - int mbsfn_period =0;// 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); - int mcch_period = 0;//32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); - int mch_scheduling_period = 8<<(RC.mac[module_idP]->common_channels[CC_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 = -1; - uint16_t TBS,j=-1,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; - uint16_t sdu_lengths[11], sdu_length_total=0; - unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only - - COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; - - cc->MCH_pdu.Pdu_size=0; - - for (i=0; - i< cc->num_active_mbsfn_area; - i++ ) { - // assume, that there is always a mapping - if ((j=get_mbsfn_sf_alloction(module_idP,CC_id,i)) == -1) { - return 0; - } - - mbsfn_period = 1<<(cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod); - mcch_period = 32<<(cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9); - msi_pos=0; - ii=0; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n", - module_idP, CC_id, frameP, subframeP,i,cc->num_active_mbsfn_area, - j,cc->num_sf_allocation_pattern,mbsfn_period,mcch_period); - - - switch (cc->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 (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP - if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format - - // Find the first subframeP in this MCH to transmit MSI - if (frameP % mch_scheduling_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) { - while (ii == 0) { - ii = cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos); - msi_pos++; - } - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n", - module_idP, CC_id, frameP, subframeP,i,j, - cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0], msi_pos); - } - - // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 - switch (subframeP) { - case 1: - if (cc->tdd_Config == NULL) { - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { - if (msi_pos == 1) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config == NULL) { - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config != NULL) { // TDD - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { - if (msi_pos == 1) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config != NULL) { - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config == NULL) { - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config != NULL) { // TDD - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config != NULL) { //TDD - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { - if (msi_pos == 6) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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 (cc->tdd_Config != NULL) { - if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((cc->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] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", - module_idP, CC_id, frameP, subframeP,i,j,msi_flag,mcch_flag,mtch_flag); - break; - } - } else { // four-frameP format - } + int mcch_flag = 0, mtch_flag = 0, msi_flag = 0; + int mbsfn_period = 0; // 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); + int mcch_period = 0; //32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); + int mch_scheduling_period = + 8 << (RC.mac[module_idP]->common_channels[CC_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 = -1; + uint16_t TBS, j = -1, 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; + uint16_t sdu_lengths[11], sdu_length_total = 0; + unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only + + COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; + + cc->MCH_pdu.Pdu_size = 0; + + for (i = 0; i < cc->num_active_mbsfn_area; i++) { + // assume, that there is always a mapping + if ((j = get_mbsfn_sf_alloction(module_idP, CC_id, i)) == -1) { + return 0; + } + + mbsfn_period = + 1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod); + mcch_period = + 32 << (cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_RepetitionPeriod_r9); + msi_pos = 0; + ii = 0; + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n", + module_idP, CC_id, frameP, subframeP, i, + cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern, + mbsfn_period, mcch_period); + + + switch (cc->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 (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP + if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format + + // Find the first subframeP in this MCH to transmit MSI + if (frameP % mch_scheduling_period == + cc->mbsfn_SubframeConfig[j]-> + radioframeAllocationOffset) { + while (ii == 0) { + ii = cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & (0x80 >> msi_pos); + msi_pos++; + } + + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n", + module_idP, CC_id, frameP, subframeP, i, j, + cc->mbsfn_SubframeConfig[j]-> + subframeAllocation.choice.oneFrame.buf[0], + msi_pos); + } + // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 + switch (subframeP) { + case 1: + if (cc->tdd_Config == NULL) { + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == + MBSFN_FDD_SF1) { + if (msi_pos == 1) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config == NULL) { + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == + MBSFN_FDD_SF2) { + if (msi_pos == 2) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config != NULL) { // TDD + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == + MBSFN_TDD_SF3) { + if (msi_pos == 1) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == + MBSFN_FDD_SF3) { + if (msi_pos == 3) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config != NULL) { + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == + MBSFN_TDD_SF4) { + if (msi_pos == 2) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config == NULL) { + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == + MBSFN_FDD_SF6) { + if (msi_pos == 4) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config != NULL) { // TDD + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == + MBSFN_TDD_SF7) { + if (msi_pos == 3) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == + MBSFN_FDD_SF7) { + if (msi_pos == 5) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config != NULL) { //TDD + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == + MBSFN_TDD_SF8) { + if (msi_pos == 4) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == + MBSFN_FDD_SF8) { + if (msi_pos == 6) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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 (cc->tdd_Config != NULL) { + if ((cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == + MBSFN_TDD_SF9) { + if (msi_pos == 5) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_Offset_r9) + && + ((cc->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] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", + module_idP, CC_id, frameP, subframeP, i, j, + msi_flag, mcch_flag, mtch_flag); + break; + } + } else { // four-frameP format + } + } + } // end of for loop + + cc->msi_active = 0; + cc->mcch_active = 0; + cc->mtch_active = 0; + + // Calculate the mcs + if ((msi_flag == 1) || (mcch_flag == 1)) { + cc->MCH_pdu.mcs = mcch_mcs; + } else if (mtch_flag == 1) { // only MTCH in this subframeP + cc->MCH_pdu.mcs = cc->pmch_Config[0]->dataMCS_r9; } - } // end of for loop - - cc->msi_active=0; - cc->mcch_active=0; - cc->mtch_active=0; - - // Calculate the mcs - if ((msi_flag==1) || (mcch_flag==1)) { - cc->MCH_pdu.mcs = mcch_mcs; - } else if (mtch_flag == 1) { // only MTCH in this subframeP - cc->MCH_pdu.mcs = cc->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 - uint16_t 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; + // 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC + + // there is MSI (MCH Scheduling Info) + if (msi_flag == 1) { + // Create MSI here + uint16_t 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 = cc->mbms_SessionList[0]->list.count; + + for (k = 0; k < num_mtch; k++) { // loop for all session in this MCH (MCH[0]) at this moment + ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9; //mtch_lcid; + ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP 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] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes \n", + module_idP, CC_id, frameP, msi_length); + //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \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] CC_id %d Create %d bytes for MSI\n", + module_idP, CC_id, sdu_lengths[num_sdus]); + num_sdus++; + cc->msi_active = 1; } - - msi_ptr+= sizeof(MSI_ELEMENT); - - //Header for MTCHs - num_mtch = cc->mbms_SessionList[0]->list.count; - - for (k=0; k<num_mtch; k++) { // loop for all session in this MCH (MCH[0]) at this moment - ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9;//mtch_lcid; - ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now) - ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xB; - msi_ptr+=sizeof(MSI_ELEMENT); + // there is MCCH + if (mcch_flag == 1) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n", + module_idP, CC_id, frameP, subframeP, i, j); + + mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 1, &cc->MCCH_pdu.payload[0], 1, // this is eNB + module_idP, // index + i); // this is the mbsfn sync area index + + if (mcch_sdu_length > 0) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n", + module_idP, CC_id, frameP, subframeP, mcch_sdu_length); + + header_len_mcch = 2; + + if (cc->tdd_Config != NULL) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } else { + LOG_I(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } + + cc->mcch_active = 1; + + memcpy((char *) &mch_buffer[sdu_length_total], + &cc->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] CC_id %d Got %d bytes for MCCH from RRC \n", + module_idP, CC_id, sdu_lengths[num_sdus]); + num_sdus++; + } } - 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] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes \n", - module_idP,CC_id,frameP,msi_length); - //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \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] CC_id %d Create %d bytes for MSI\n", module_idP, CC_id, sdu_lengths[num_sdus]); - num_sdus++; - cc->msi_active=1; - } - - // there is MCCH - if (mcch_flag == 1) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n", - module_idP, CC_id, frameP, subframeP, i, j); - - mcch_sdu_length = mac_rrc_data_req(module_idP, - CC_id, - frameP, - MCCH,1, - &cc->MCCH_pdu.payload[0], - 1,// this is eNB - module_idP, // index - i); // this is the mbsfn sync area index - - if (mcch_sdu_length > 0) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n", - module_idP,CC_id,frameP,subframeP,mcch_sdu_length); - - header_len_mcch = 2; - - if (cc->tdd_Config != NULL) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", - module_idP, CC_id, - frameP,subframeP, - mcch_sdu_length, - mcch_mcs); - } else { - LOG_I(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", - module_idP, CC_id, - frameP, subframeP, - mcch_sdu_length, - mcch_mcs); - } - - cc->mcch_active=1; - - memcpy((char *)&mch_buffer[sdu_length_total], - &cc->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] CC_id %d Got %d bytes for MCCH from RRC \n",module_idP,CC_id,sdu_lengths[num_sdus]); - num_sdus++; - } - } - - TBS = get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth)); + TBS = + get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth)); #if defined(Rel10) || defined(Rel14) - // do not let mcch and mtch multiplexing when relaying is active - // for sync area 1, so not transmit data - //if ((i == 0) && ((RC.mac[module_idP]->MBMS_flag != multicast_relay) || (RC.mac[module_idP]->mcch_active==0))) { + // do not let mcch and mtch multiplexing when relaying is active + // for sync area 1, so not transmit data + //if ((i == 0) && ((RC.mac[module_idP]->MBMS_flag != multicast_relay) || (RC.mac[module_idP]->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->frame_parms->N_RB_DL); - } - else { // only MTCH in this subframeP - TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL); - } - - // get MTCH data from RLC (like for DTCH) - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j); - - header_len_mtch = 3; - LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", - Mod_id,CC_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); - - */ - - // get MTCH data from RLC (like for DTCH) - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n",module_idP,CC_id,frameP,subframeP,i,j); - - header_len_mtch = 3; - LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", - module_idP,CC_id,frameP,MTCH,TBS, - TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); - - rlc_status = mac_rlc_status_ind(module_idP,0,frameP,subframeP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH, - TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); - LOG_D(MAC,"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n", - MTCH,frameP,subframeP, rlc_status.bytes_in_buffer); - - if (rlc_status.bytes_in_buffer >0) { - LOG_I(MAC,"[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n", - module_idP,CC_id,frameP,TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch,header_len_mtch); - - sdu_lengths[num_sdus] = mac_rlc_data_req( - module_idP, - 0, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_YES, - MTCH, - 0, //not used - (char*)&mch_buffer[sdu_length_total]); - //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]); - LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",module_idP,CC_id,sdu_lengths[num_sdus],MTCH); - cc->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; + // 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->frame_parms->N_RB_DL); + } + else { // only MTCH in this subframeP + TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL); + } + + // get MTCH data from RLC (like for DTCH) + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j); + + header_len_mtch = 3; + LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", + Mod_id,CC_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); + + */ + + // get MTCH data from RLC (like for DTCH) + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n", + module_idP, CC_id, frameP, subframeP, i, j); + + header_len_mtch = 3; + LOG_D(MAC, + "[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", + module_idP, CC_id, frameP, MTCH, TBS, + TBS - header_len_mcch - header_len_msi - sdu_length_total - + header_len_mtch); + + rlc_status = + mac_rlc_status_ind(module_idP, 0, frameP, subframeP, + module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, + MTCH, + TBS - header_len_mcch - header_len_msi - + sdu_length_total - header_len_mtch); + LOG_D(MAC, + "e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n", + MTCH, frameP, subframeP, rlc_status.bytes_in_buffer); + + if (rlc_status.bytes_in_buffer > 0) { + LOG_I(MAC, + "[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d)\n", + module_idP, CC_id, frameP, + TBS - header_len_mcch - header_len_msi - + sdu_length_total - header_len_mtch, header_len_mtch); + + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES, MTCH, 0, //not used + (char *) + &mch_buffer + [sdu_length_total]); + //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]); + LOG_I(MAC, + "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n", + module_idP, CC_id, sdu_lengths[num_sdus], MTCH); + cc->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; + } } - } - #if defined(Rel10) || defined(Rel14) - // } + // } #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)) { - RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs; - } - else if (mtch_flag == 1) { // only MTCH in this subframeP - RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->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; + // 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)) { + RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs; + } + else if (mtch_flag == 1) { // only MTCH in this subframeP + RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->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) < 0) { + LOG_E(MAC, "Error in building MAC PDU, TBS %d < PDU %d \n", + TBS, + header_len_mtch + header_len_mcch + header_len_msi + + sdu_length_total); + return 0; + } else + 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 *) cc->MCH_pdu.payload, num_sdus, sdu_lengths, sdu_lcids, 255, // no drx + 31, // no timing advance + NULL, // no contention res id + padding, post_padding); + + cc->MCH_pdu.Pdu_size = TBS; + cc->MCH_pdu.sync_area = i; + cc->MCH_pdu.msi_active = cc->msi_active; + cc->MCH_pdu.mcch_active = cc->mcch_active; + cc->MCH_pdu.mtch_active = cc->mtch_active; + LOG_D(MAC, + " MCS for this sf is %d (mcch active %d, mtch active %d)\n", + cc->MCH_pdu.mcs, cc->MCH_pdu.mcch_active, + cc->MCH_pdu.mtch_active); + LOG_I(MAC, + "[eNB %d][MBMS USER-PLANE ] CC_id %d 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", + module_idP, CC_id, sdu_length_total, num_sdus, + sdu_lengths[0], sdu_lcids[0], offset, padding, post_padding, + cc->MCH_pdu.mcs, TBS, header_len_mtch, header_len_mcch, + header_len_msi); + // copy SDU to mch_pdu after the MAC Header + memcpy(&cc->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++) { + cc->MCH_pdu.payload[offset + sdu_length_total + j] = + (char) (taus() & 0xff); + } + + /* Tracing of PDU is done on UE side */ + if (opt_enabled == 1) { + trace_pdu(1, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, 6, 0xffff, // M_RNTI = 6 in wirehsark + RC.mac[module_idP]->frame, + RC.mac[module_idP]->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n", + module_idP, CC_id, frameP, TBS); + } + + /* + for (j=0;j<sdu_length_total;j++) + printf("%2x.",RC.mac[module_idP]->MCH_pdu.payload[j+offset]); + printf(" \n"); */ + return 1; } else { - header_len_msi=1; - } - - // Calculate the padding - if ((TBS - header_len_mtch - header_len_mcch - header_len_msi - sdu_length_total) < 0) { - LOG_E(MAC,"Error in building MAC PDU, TBS %d < PDU %d \n", - TBS, header_len_mtch + header_len_mcch + header_len_msi + sdu_length_total); - return 0; - } else 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*)cc->MCH_pdu.payload, - num_sdus, - sdu_lengths, - sdu_lcids, - 255, // no drx - 31, // no timing advance - NULL, // no contention res id - padding, - post_padding); - - cc->MCH_pdu.Pdu_size=TBS; - cc->MCH_pdu.sync_area=i; - cc->MCH_pdu.msi_active= cc->msi_active; - cc->MCH_pdu.mcch_active= cc->mcch_active; - cc->MCH_pdu.mtch_active= cc->mtch_active; - LOG_D(MAC," MCS for this sf is %d (mcch active %d, mtch active %d)\n", cc->MCH_pdu.mcs, - cc->MCH_pdu.mcch_active,cc->MCH_pdu.mtch_active ); - LOG_I(MAC, - "[eNB %d][MBMS USER-PLANE ] CC_id %d 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", - module_idP,CC_id,sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset,padding,post_padding,cc->MCH_pdu.mcs,TBS, - header_len_mtch, header_len_mcch, header_len_msi); - // copy SDU to mch_pdu after the MAC Header - memcpy(&cc->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++) { - cc->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff); - } - - /* Tracing of PDU is done on UE side */ - if (opt_enabled ==1 ) { - trace_pdu(1, (uint8_t *)cc->MCH_pdu.payload, - TBS, module_idP, 6, 0xffff, // M_RNTI = 6 in wirehsark - RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe,0,0); - LOG_D(OPT,"[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n", - module_idP, CC_id, frameP, TBS); + cc->MCH_pdu.Pdu_size = 0; + cc->MCH_pdu.sync_area = 0; + cc->MCH_pdu.msi_active = 0; + cc->MCH_pdu.mcch_active = 0; + cc->MCH_pdu.mtch_active = 0; + // for testing purpose, fill with random data + //for (j=0;j<(TBS-sdu_length_total-offset);j++) + // RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff); + return 0; } + //this is for testing /* - for (j=0;j<sdu_length_total;j++) - printf("%2x.",RC.mac[module_idP]->MCH_pdu.payload[j+offset]); - printf(" \n");*/ - return 1; - } else { - cc->MCH_pdu.Pdu_size=0; - cc->MCH_pdu.sync_area=0; - cc->MCH_pdu.msi_active=0; - cc->MCH_pdu.mcch_active=0; - cc->MCH_pdu.mtch_active=0; - // for testing purpose, fill with random data - //for (j=0;j<(TBS-sdu_length_total-offset);j++) - // RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff); - return 0; - } - - //this is for testing - /* - if (mtch_flag == 1) { - // LOG_D(MAC,"DUY: mch_buffer length so far is : %ld\n", &mch_buffer[sdu_length_total]-&mch_buffer[0]); - return 1; - } - else - return 0; - */ + if (mtch_flag == 1) { + // LOG_D(MAC,"DUY: mch_buffer length so far is : %ld\n", &mch_buffer[sdu_length_total]-&mch_buffer[0]); + return 1; + } + else + return 0; + */ } -MCH_PDU *get_mch_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframeP) +MCH_PDU *get_mch_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframeP) { - // RC.mac[module_idP]->MCH_pdu.mcs=0; - //LOG_D(MAC," MCH_pdu.mcs is %d\n", RC.mac[module_idP]->MCH_pdu.mcs); + // RC.mac[module_idP]->MCH_pdu.mcs=0; + //LOG_D(MAC," MCH_pdu.mcs is %d\n", RC.mac[module_idP]->MCH_pdu.mcs); //#warning "MCH pdu should take the CC_id index" - return(&RC.mac[module_idP]->common_channels[CC_id].MCH_pdu); + return (&RC.mac[module_idP]->common_channels[CC_id].MCH_pdu); } #endif diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 08b04f518859a958a1efab0d589c3c87cb5dd8a2..8b88bef244078eba236f2d2d4224e39f8e0548ea 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -53,7 +53,7 @@ #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #include "T.h" @@ -61,1449 +61,1781 @@ #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 -int choose(int n,int k) +int choose(int n, int k) { - int res = 1; - int res2 = 1; - int i; + int res = 1; + int res2 = 1; + int i; - if (k>n) return(0); - if (n==k) return(1); + if (k > n) + return (0); + if (n == k) + return (1); - for (i=n;i>k;i--) res*=i; - for (i=2;i<=(n-k);i++) res2*=i; + for (i = n; i > k; i--) + res *= i; + for (i = 2; i <= (n - k); i++) + res2 *= i; - return(res/res2); + return (res / res2); } // Patented algorithm from Yang et al, US Patent 2009, "Channel Quality Indexing and Reverse Indexing" -void reverse_index(int N,int M,int r,int *v) -{ - int BaseValue=0; - int IncreaseValue,ThresholdValue; - int sumV; - int i; - - r = choose(N,M) - 1 - r; - memset((void*)v,0,M*sizeof(int)); - - sumV=0; - i=M; - while (i>0 && r>0) { - IncreaseValue = choose(N-M+1-sumV-v[i-1]+i-2,i-1); - ThresholdValue = BaseValue+IncreaseValue; - if (r>=ThresholdValue) { - v[i-1]++; - BaseValue=ThresholdValue; - } - else { - r=r-BaseValue; - sumV+=v[i-1]; - i--; - BaseValue=0; +void reverse_index(int N, int M, int r, int *v) +{ + int BaseValue = 0; + int IncreaseValue, ThresholdValue; + int sumV; + int i; + + r = choose(N, M) - 1 - r; + memset((void *) v, 0, M * sizeof(int)); + + sumV = 0; + i = M; + while (i > 0 && r > 0) { + IncreaseValue = choose(N - M + 1 - sumV - v[i - 1] + i - 2, i - 1); + ThresholdValue = BaseValue + IncreaseValue; + if (r >= ThresholdValue) { + v[i - 1]++; + BaseValue = ThresholdValue; + } else { + r = r - BaseValue; + sumV += v[i - 1]; + i--; + BaseValue = 0; + } } - } } int to_prb(int dl_Bandwidth) { - int prbmap[6] = {6,15,25,50,75,100}; + int prbmap[6] = { 6, 15, 25, 50, 75, 100 }; - AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n"); - return(prbmap[dl_Bandwidth]); + AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth is 0..5\n"); + return (prbmap[dl_Bandwidth]); } int to_rbg(int dl_Bandwidth) { - int rbgmap[6] = {6,8,13,17,19,25}; + int rbgmap[6] = { 6, 8, 13, 17, 19, 25 }; - AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n"); - return(rbgmap[dl_Bandwidth]); + AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth is 0..5\n"); + return (rbgmap[dl_Bandwidth]); } -int get_phich_resource_times6(COMMON_channels_t *cc) +int get_phich_resource_times6(COMMON_channels_t * cc) { - int phichmap[4] = {1,3,6,12}; - AssertFatal(cc!=NULL,"cc is null\n"); - AssertFatal(cc->mib!=NULL,"cc->mib is null\n"); - AssertFatal((cc->mib->message.phich_Config.phich_Resource>=0) && - (cc->mib->message.phich_Config.phich_Resource<4), - "phich_Resource %d not in 0..3\n",(int)cc->mib->message.phich_Config.phich_Resource); - - return(phichmap[cc->mib->message.phich_Config.phich_Resource]); + int phichmap[4] = { 1, 3, 6, 12 }; + AssertFatal(cc != NULL, "cc is null\n"); + AssertFatal(cc->mib != NULL, "cc->mib is null\n"); + AssertFatal((cc->mib->message.phich_Config.phich_Resource >= 0) && + (cc->mib->message.phich_Config.phich_Resource < 4), + "phich_Resource %d not in 0..3\n", + (int) cc->mib->message.phich_Config.phich_Resource); + + return (phichmap[cc->mib->message.phich_Config.phich_Resource]); } -uint16_t mac_computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs) +uint16_t mac_computeRIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs) { - uint16_t RIV; + uint16_t RIV; - if (Lcrbs<=(1+(N_RB_DL>>1))) - RIV = (N_RB_DL*(Lcrbs-1)) + RBstart; - else - RIV = (N_RB_DL*(N_RB_DL+1-Lcrbs)) + (N_RB_DL-1-RBstart); + if (Lcrbs <= (1 + (N_RB_DL >> 1))) + RIV = (N_RB_DL * (Lcrbs - 1)) + RBstart; + else + RIV = (N_RB_DL * (N_RB_DL + 1 - Lcrbs)) + (N_RB_DL - 1 - RBstart); - return(RIV); + return (RIV); } uint8_t getQm(uint8_t mcs) { - if (mcs<10) return(2); - else if (mcs<17) return(4); - else return (6); + if (mcs < 10) + return (2); + else if (mcs < 17) + return (4); + else + return (6); } -void get_Msg3alloc(COMMON_channels_t *cc, - - sub_frame_t current_subframe, - frame_t current_frame, - frame_t *frame, - sub_frame_t *subframe) +void +get_Msg3alloc(COMMON_channels_t * cc, + sub_frame_t current_subframe, + frame_t current_frame, frame_t * frame, + sub_frame_t * subframe) { - // Fill in other TDD Configuration!!!! - - if (cc->tdd_Config==NULL) { // FDD - *subframe = current_subframe+6; - - if (*subframe>9) { - *subframe = *subframe-10; - *frame = (current_frame+1) & 1023; - } else { - *frame=current_frame; - } - } else { // TDD - if (cc->tdd_Config->subframeAssignment == 1) { - switch (current_subframe) { - - case 0: - *subframe = 7; - *frame = current_frame; - break; - - case 4: - *subframe = 2; - *frame = (current_frame+1) & 1023; - break; - - case 5: - *subframe = 2; - *frame = (current_frame+1) & 1023; - break; - - case 9: - *subframe = 7; - *frame = (current_frame+1) & 1023; - break; - } - } else if (cc->tdd_Config->subframeAssignment == 3) { - switch (current_subframe) { - - case 0: - case 5: - case 6: - *subframe = 2; - *frame = (current_frame+1) & 1023; - break; - - case 7: - *subframe = 3; - *frame = (current_frame+1) & 1023; - break; - - case 8: - *subframe = 4; - *frame = (current_frame+1) & 1023; - break; - - case 9: - *subframe = 2; - *frame = (current_frame+2) & 1023; - break; - } - } else if (cc->tdd_Config->subframeAssignment == 4) { - switch (current_subframe) { - - case 0: - case 4: - case 5: - case 6: - *subframe = 2; - *frame = (current_frame+1) & 1023; - break; - - case 7: - *subframe = 3; - *frame = (current_frame+1) & 1023; - break; - - case 8: - case 9: - *subframe = 2; - *frame = (current_frame+2) & 1023; - break; - } - } else if (cc->tdd_Config->subframeAssignment == 5) { - switch (current_subframe) { - - case 0: - case 4: - case 5: - case 6: - *subframe = 2; - *frame = (current_frame+1) & 1023; - break; - - case 7: - case 8: - case 9: - *subframe = 2; - *frame = (current_frame+2) & 1023; - break; - } + // Fill in other TDD Configuration!!!! + + if (cc->tdd_Config == NULL) { // FDD + *subframe = current_subframe + 6; + + if (*subframe > 9) { + *subframe = *subframe - 10; + *frame = (current_frame + 1) & 1023; + } else { + *frame = current_frame; + } + } else { // TDD + if (cc->tdd_Config->subframeAssignment == 1) { + switch (current_subframe) { + + case 0: + *subframe = 7; + *frame = current_frame; + break; + + case 4: + *subframe = 2; + *frame = (current_frame + 1) & 1023; + break; + + case 5: + *subframe = 2; + *frame = (current_frame + 1) & 1023; + break; + + case 9: + *subframe = 7; + *frame = (current_frame + 1) & 1023; + break; + } + } else if (cc->tdd_Config->subframeAssignment == 3) { + switch (current_subframe) { + + case 0: + case 5: + case 6: + *subframe = 2; + *frame = (current_frame + 1) & 1023; + break; + + case 7: + *subframe = 3; + *frame = (current_frame + 1) & 1023; + break; + + case 8: + *subframe = 4; + *frame = (current_frame + 1) & 1023; + break; + + case 9: + *subframe = 2; + *frame = (current_frame + 2) & 1023; + break; + } + } else if (cc->tdd_Config->subframeAssignment == 4) { + switch (current_subframe) { + + case 0: + case 4: + case 5: + case 6: + *subframe = 2; + *frame = (current_frame + 1) & 1023; + break; + + case 7: + *subframe = 3; + *frame = (current_frame + 1) & 1023; + break; + + case 8: + case 9: + *subframe = 2; + *frame = (current_frame + 2) & 1023; + break; + } + } else if (cc->tdd_Config->subframeAssignment == 5) { + switch (current_subframe) { + + case 0: + case 4: + case 5: + case 6: + *subframe = 2; + *frame = (current_frame + 1) & 1023; + break; + + case 7: + case 8: + case 9: + *subframe = 2; + *frame = (current_frame + 2) & 1023; + break; + } + } } - } } -void get_Msg3allocret(COMMON_channels_t *cc, - sub_frame_t current_subframe, - frame_t current_frame, - frame_t *frame, - sub_frame_t *subframe) +void +get_Msg3allocret(COMMON_channels_t * cc, + sub_frame_t current_subframe, + frame_t current_frame, + frame_t * frame, sub_frame_t * subframe) { - if (cc->tdd_Config == NULL) { //FDD - /* always retransmit in n+8 */ - *subframe = current_subframe + 8; - - if (*subframe > 9) { - *subframe = *subframe - 10; - *frame = (current_frame + 1) & 1023; + if (cc->tdd_Config == NULL) { //FDD + /* always retransmit in n+8 */ + *subframe = current_subframe + 8; + + if (*subframe > 9) { + *subframe = *subframe - 10; + *frame = (current_frame + 1) & 1023; + } else { + *frame = current_frame; + } } else { - *frame = current_frame; - } - } else { - if (cc->tdd_Config->subframeAssignment == 1) { - // original PUSCH in 2, PHICH in 6 (S), ret in 2 - // original PUSCH in 3, PHICH in 9, ret in 3 - // original PUSCH in 7, PHICH in 1 (S), ret in 7 - // original PUSCH in 8, PHICH in 4, ret in 8 - *frame = (current_frame+1) & 1023; - } else if (cc->tdd_Config->subframeAssignment == 3) { - // original PUSCH in 2, PHICH in 8, ret in 2 next frame - // original PUSCH in 3, PHICH in 9, ret in 3 next frame - // original PUSCH in 4, PHICH in 0, ret in 4 next frame - *frame=(current_frame+1) & 1023; - } else if (cc->tdd_Config->subframeAssignment == 4) { - // original PUSCH in 2, PHICH in 8, ret in 2 next frame - // original PUSCH in 3, PHICH in 9, ret in 3 next frame - *frame=(current_frame+1) & 1023; - } else if (cc->tdd_Config->subframeAssignment == 5) { - // original PUSCH in 2, PHICH in 8, ret in 2 next frame - *frame=(current_frame+1) & 1023; + if (cc->tdd_Config->subframeAssignment == 1) { + // original PUSCH in 2, PHICH in 6 (S), ret in 2 + // original PUSCH in 3, PHICH in 9, ret in 3 + // original PUSCH in 7, PHICH in 1 (S), ret in 7 + // original PUSCH in 8, PHICH in 4, ret in 8 + *frame = (current_frame + 1) & 1023; + } else if (cc->tdd_Config->subframeAssignment == 3) { + // original PUSCH in 2, PHICH in 8, ret in 2 next frame + // original PUSCH in 3, PHICH in 9, ret in 3 next frame + // original PUSCH in 4, PHICH in 0, ret in 4 next frame + *frame = (current_frame + 1) & 1023; + } else if (cc->tdd_Config->subframeAssignment == 4) { + // original PUSCH in 2, PHICH in 8, ret in 2 next frame + // original PUSCH in 3, PHICH in 9, ret in 3 next frame + *frame = (current_frame + 1) & 1023; + } else if (cc->tdd_Config->subframeAssignment == 5) { + // original PUSCH in 2, PHICH in 8, ret in 2 next frame + *frame = (current_frame + 1) & 1023; + } } - } } -uint8_t subframe2harqpid(COMMON_channels_t *cc,frame_t frame,sub_frame_t subframe) +uint8_t +subframe2harqpid(COMMON_channels_t * cc, frame_t frame, + sub_frame_t subframe) { - uint8_t ret = 255; + uint8_t ret = 255; - AssertFatal(cc!=NULL,"cc is null\n"); + AssertFatal(cc != NULL, "cc is null\n"); - if (cc->tdd_Config == NULL) { // FDD - ret = (((frame<<1)+subframe)&7); - } else { - switch (cc->tdd_Config->subframeAssignment) { - case 1: - if ((subframe==2) || - (subframe==3) || - (subframe==7) || - (subframe==8)) - switch (subframe) { - case 2: - case 3: - ret = (subframe-2); - break; - - case 7: - case 8: - ret = (subframe-5); - break; - - default: - AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment); - break; - } - - break; + if (cc->tdd_Config == NULL) { // FDD + ret = (((frame << 1) + subframe) & 7); + } else { + switch (cc->tdd_Config->subframeAssignment) { + case 1: + if ((subframe == 2) || + (subframe == 3) || (subframe == 7) || (subframe == 8)) + switch (subframe) { + case 2: + case 3: + ret = (subframe - 2); + break; + + case 7: + case 8: + ret = (subframe - 5); + break; + + default: + AssertFatal(1 == 0, + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframe, + (int) cc->tdd_Config->subframeAssignment); + break; + } + + break; + + case 2: + AssertFatal((subframe == 2) || (subframe == 7), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframe, + (int) cc->tdd_Config->subframeAssignment); + + ret = (subframe / 7); + break; + + case 3: + AssertFatal((subframe > 1) && (subframe < 5), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframe, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframe - 2); + break; + + case 4: + AssertFatal((subframe > 1) && (subframe < 4), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframe, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframe - 2); + break; + + case 5: + AssertFatal(subframe == 2, + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframe, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframe - 2); + break; + + default: + AssertFatal(1 == 0, + "subframe2_harq_pid, Unsupported TDD mode %d\n", + (int) cc->tdd_Config->subframeAssignment); + } + } + return ret; +} - case 2: - AssertFatal((subframe==2) || (subframe==7), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment); +uint8_t +get_Msg3harqpid(COMMON_channels_t * cc, + frame_t frame, sub_frame_t current_subframe) +{ + uint8_t ul_subframe = 0; + uint32_t ul_frame = 0; + + if (cc->tdd_Config == NULL) { // FDD + ul_subframe = + (current_subframe > + 3) ? (current_subframe - 4) : (current_subframe + 6); + ul_frame = (current_subframe > 3) ? ((frame + 1) & 1023) : frame; + } else { + switch (cc->tdd_Config->subframeAssignment) { + case 1: + switch (current_subframe) { + case 9: + case 0: + ul_subframe = 7; + break; + + case 5: + case 7: + ul_subframe = 2; + break; + + } + + break; + + case 3: + switch (current_subframe) { + case 0: + case 5: + case 6: + ul_subframe = 2; + break; + + case 7: + ul_subframe = 3; + break; + + case 8: + ul_subframe = 4; + break; + + case 9: + ul_subframe = 2; + break; + } + + break; + + case 4: + switch (current_subframe) { + case 0: + case 5: + case 6: + case 8: + case 9: + ul_subframe = 2; + break; + + case 7: + ul_subframe = 3; + break; + } + + break; + + case 5: + ul_subframe = 2; + break; + + default: + LOG_E(PHY, + "get_Msg3_harq_pid: Unsupported TDD configuration %d\n", + (int) cc->tdd_Config->subframeAssignment); + AssertFatal(1 == 0, + "get_Msg3_harq_pid: Unsupported TDD configuration"); + break; + } + } - ret = (subframe/7); - break; + return (subframe2harqpid(cc, ul_frame, ul_subframe)); +} - case 3: - AssertFatal((subframe>1) && (subframe<5), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment); - ret = (subframe-2); - break; +uint32_t +pdcchalloc2ulframe(COMMON_channels_t * ccP, uint32_t frame, uint8_t n) +{ + uint32_t ul_frame; + + if ((ccP->tdd_Config) && (ccP->tdd_Config->subframeAssignment == 1) && ((n == 1) || (n == 6))) // tdd_config 0,1 SF 1,5 + ul_frame = (frame + (n == 1 ? 0 : 1)); + else if ((ccP->tdd_Config) && + (ccP->tdd_Config->subframeAssignment == 6) && + ((n == 0) || (n == 1) || (n == 5) || (n == 6))) + ul_frame = (frame + (n >= 5 ? 1 : 0)); + else if ((ccP->tdd_Config) && (ccP->tdd_Config->subframeAssignment == 6) && (n == 9)) // tdd_config 6 SF 9 + ul_frame = (frame + 1); + else + ul_frame = (frame + (n >= 6 ? 1 : 0)); - case 4: - AssertFatal((subframe>1) && (subframe<4), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment); - ret = (subframe-2); - break; + LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, + ul_frame); + return ul_frame; +} - case 5: - AssertFatal(subframe==2, - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment); - ret = (subframe-2); - break; +uint8_t pdcchalloc2ulsubframe(COMMON_channels_t * ccP, uint8_t n) +{ + uint8_t ul_subframe; + + if ((ccP->tdd_Config) && (ccP->tdd_Config->subframeAssignment == 1) && ((n == 1) || (n == 6))) // tdd_config 0,1 SF 1,5 + ul_subframe = ((n + 6) % 10); + else if ((ccP->tdd_Config) && + (ccP->tdd_Config->subframeAssignment == 6) && + ((n == 0) || (n == 1) || (n == 5) || (n == 6))) + ul_subframe = ((n + 7) % 10); + else if ((ccP->tdd_Config) && (ccP->tdd_Config->subframeAssignment == 6) && (n == 9)) // tdd_config 6 SF 9 + ul_subframe = ((n + 5) % 10); + else + ul_subframe = ((n + 4) % 10); - default: - AssertFatal(1==0,"subframe2_harq_pid, Unsupported TDD mode %d\n",(int)cc->tdd_Config->subframeAssignment); - } - } - return ret; + LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe); + return ul_subframe; } -uint8_t get_Msg3harqpid(COMMON_channels_t *cc, - frame_t frame, - sub_frame_t current_subframe) +int is_UL_sf(COMMON_channels_t * ccP, sub_frame_t subframeP) { - uint8_t ul_subframe=0; - uint32_t ul_frame=0; + // if FDD return dummy value + if (ccP->tdd_Config == NULL) + return (0); - if (cc->tdd_Config == NULL) { // FDD - ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6); - ul_frame = (current_subframe>3) ? ((frame+1)&1023) : frame; - } else { - switch (cc->tdd_Config->subframeAssignment) { + switch (ccP->tdd_Config->subframeAssignment) { case 1: - switch (current_subframe) { - case 9: - case 0: - ul_subframe = 7; - break; - - case 5: - case 7: - ul_subframe = 2; - break; - - } - - break; + switch (subframeP) { + case 0: + case 4: + case 5: + case 9: + return (0); + break; + + case 2: + case 3: + case 7: + case 8: + return (1); + break; + + default: + return (0); + break; + } + break; case 3: - switch (current_subframe) { - case 0: - case 5: - case 6: - ul_subframe = 2; - break; - - case 7: - ul_subframe = 3; - break; - - case 8: - ul_subframe = 4; - break; - - case 9: - ul_subframe = 2; - break; - } - - break; + if ((subframeP <= 1) || (subframeP >= 5)) + return (0); + else if ((subframeP > 1) && (subframeP < 5)) + return (1); + else + AssertFatal(1 == 0, "Unknown subframe number\n"); + break; case 4: - switch (current_subframe) { - case 0: - case 5: - case 6: - case 8: - case 9: - ul_subframe = 2; - break; - - case 7: - ul_subframe = 3; - break; - } - - break; + if ((subframeP <= 1) || (subframeP >= 4)) + return (0); + else if ((subframeP > 1) && (subframeP < 4)) + return (1); + else + AssertFatal(1 == 0, "Unknown subframe number\n"); + break; case 5: - ul_subframe =2; - break; + if ((subframeP <= 1) || (subframeP >= 3)) + return (0); + else if ((subframeP > 1) && (subframeP < 3)) + return (1); + else + AssertFatal(1 == 0, "Unknown subframe number\n"); + break; default: - LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",(int)cc->tdd_Config->subframeAssignment); - AssertFatal(1==0,"get_Msg3_harq_pid: Unsupported TDD configuration"); - break; + AssertFatal(1 == 0, + "subframe %d Unsupported TDD configuration %d\n", + subframeP, (int) ccP->tdd_Config->subframeAssignment); + break; } - } - - return(subframe2harqpid(cc,ul_frame,ul_subframe)); } -uint32_t pdcchalloc2ulframe(COMMON_channels_t *ccP,uint32_t frame, uint8_t n) +uint16_t get_pucch1_absSF(COMMON_channels_t * cc, uint16_t dlsch_absSF) { - uint32_t ul_frame; - - if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 1) && - ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5 - ul_frame = (frame + (n==1 ? 0 : 1)); - else if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 6) && - ((n==0)||(n==1)||(n==5)||(n==6))) - ul_frame = (frame + (n>=5 ? 1 : 0)); - else if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 6) && - (n==9)) // tdd_config 6 SF 9 - ul_frame = (frame+1); - else - ul_frame = (frame+(n>=6 ? 1 : 0)); + uint16_t sf, f, nextf; - LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame); - return ul_frame; + if (cc->tdd_Config == NULL) { //FDD n+4 + return ((dlsch_absSF + 4) % 10240); + } else { + sf = dlsch_absSF % 10; + f = dlsch_absSF / 10; + nextf = (f + 1) & 1023; + + switch (cc->tdd_Config->subframeAssignment) { + case 0: + AssertFatal(1 == 0, "SFA 0 to be filled in now, :-)\n"); + break; + case 1: + if ((sf == 5) || (sf == 6)) + return ((10 * nextf) + 2); // ACK/NAK in SF 2 next frame + else if (sf == 9) + return ((10 * nextf) + 3); // ACK/NAK in SF 3 next frame + else if ((sf == 0) || (sf == 1)) + return ((10 * f) + 2); // ACK/NAK in SF 7 same frame + else + AssertFatal(1 == 0, + "Impossible dlsch subframe %d for TDD configuration 3\n", + sf); + break; + case 2: + if ((sf == 4) || (sf == 5) || (sf == 6) || (sf == 8)) + return ((10 * nextf) + 2); // ACK/NAK in SF 2 next frame + else if (sf == 9) + return ((10 * nextf) + 7); // ACK/NAK in SF 7 next frame + else if ((sf == 0) || (sf == 1) || (sf == 3)) + return ((10 * f) + 7); // ACK/NAK in SF 7 same frame + else + AssertFatal(1 == 0, + "Impossible dlsch subframe %d for TDD configuration 3\n", + sf); + break; + case 3: + if ((sf == 5) || (sf == 6) || (sf == 7) || (sf == 8) + || (sf == 9)) + return ((10 * nextf) + (sf >> 1)); // ACK/NAK in 2,3,4 resp. next frame + else if (sf == 1) + return ((10 * nextf) + 2); // ACK/NAK in 2 next frame + else if (sf == 0) + return ((10 * f) + 4); // ACK/NAK in 4 same frame + else + AssertFatal(1 == 0, + "Impossible dlsch subframe %d for TDD configuration 3\n", + sf); + break; + case 4: + if ((sf == 6) || (sf == 7) || (sf == 8) || (sf == 9)) + return (((10 * nextf) + 3) % 10240); // ACK/NAK in SF 3 next frame + else if ((sf == 0) || (sf == 1) || (sf == 4) || (sf == 5)) + return (((10 * nextf) + 2) % 10240); // ACK/NAK in SF 2 next frame + else + AssertFatal(1 == 0, + "Impossible dlsch subframe %d for TDD configuration 4\n", + sf); + break; + case 5: + if ((sf == 0) || (sf == 1) || (sf == 3) || (sf == 4) + || (sf == 5) || (sf == 6) || (sf == 7) || (sf == 8)) + return (((10 * nextf) + 2) % 10240); // ACK/NAK in SF 3 next frame + else if (sf == 9) + return (((10 * (1 + nextf)) + 2) % 10240); // ACK/NAK in SF 2 next frame + else + AssertFatal(1 == 0, + "Impossible dlsch subframe %d for TDD configuration 5\n", + sf); + break; + case 6: + AssertFatal(1 == 0, "SFA 6 To be filled in now, :-)\n"); + break; + default: + AssertFatal(1 == 0, "Illegal TDD subframe Assigment %d\n", + (int) cc->tdd_Config->subframeAssignment); + break; + } + } + AssertFatal(1 == 0, "Shouldn't get here\n"); } -uint8_t pdcchalloc2ulsubframe(COMMON_channels_t *ccP,uint8_t n) +void +get_srs_pos(COMMON_channels_t * cc, uint16_t isrs, + uint16_t * psrsPeriodicity, uint16_t * psrsOffset) { - uint8_t ul_subframe; - - if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 1) && - ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5 - ul_subframe = ((n+6)%10); - else if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 6) && - ((n==0)||(n==1)||(n==5)||(n==6))) - ul_subframe = ((n+7)%10); - else if ((ccP->tdd_Config) && - (ccP->tdd_Config->subframeAssignment == 6) && - (n==9)) // tdd_config 6 SF 9 - ul_subframe = ((n+5)%10); - else - ul_subframe = ((n+4)%10); - - LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe); - return ul_subframe; + if (cc->tdd_Config) { // TDD + AssertFatal(isrs >= 10, "2 ms SRS periodicity not supported"); + + if ((isrs > 9) && (isrs < 15)) { + *psrsPeriodicity = 5; + *psrsOffset = isrs - 10; + } + if ((isrs > 14) && (isrs < 25)) { + *psrsPeriodicity = 10; + *psrsOffset = isrs - 15; + } + if ((isrs > 24) && (isrs < 45)) { + *psrsPeriodicity = 20; + *psrsOffset = isrs - 25; + } + if ((isrs > 44) && (isrs < 85)) { + *psrsPeriodicity = 40; + *psrsOffset = isrs - 45; + } + if ((isrs > 84) && (isrs < 165)) { + *psrsPeriodicity = 80; + *psrsOffset = isrs - 85; + } + if ((isrs > 164) && (isrs < 325)) { + *psrsPeriodicity = 160; + *psrsOffset = isrs - 165; + } + if ((isrs > 324) && (isrs < 645)) { + *psrsPeriodicity = 320; + *psrsOffset = isrs - 325; + } + + AssertFatal(isrs <= 644, "Isrs out of range %d>644\n", isrs); + } // TDD + else { // FDD + if (isrs < 2) { + *psrsPeriodicity = 2; + *psrsOffset = isrs; + } + if ((isrs > 1) && (isrs < 7)) { + *psrsPeriodicity = 5; + *psrsOffset = isrs - 2; + } + if ((isrs > 6) && (isrs < 17)) { + *psrsPeriodicity = 10; + *psrsOffset = isrs - 7; + } + if ((isrs > 16) && (isrs < 37)) { + *psrsPeriodicity = 20; + *psrsOffset = isrs - 17; + } + if ((isrs > 36) && (isrs < 77)) { + *psrsPeriodicity = 40; + *psrsOffset = isrs - 37; + } + if ((isrs > 76) && (isrs < 157)) { + *psrsPeriodicity = 80; + *psrsOffset = isrs - 77; + } + if ((isrs > 156) && (isrs < 317)) { + *psrsPeriodicity = 160; + *psrsOffset = isrs - 157; + } + if ((isrs > 316) && (isrs < 637)) { + *psrsPeriodicity = 320; + *psrsOffset = isrs - 317; + } + AssertFatal(isrs <= 636, "Isrs out of range %d>636\n", isrs); + } } -int is_UL_sf(COMMON_channels_t *ccP,sub_frame_t subframeP) +void +get_csi_params(COMMON_channels_t * cc, + struct CQI_ReportPeriodic *cqi_ReportPeriodic, + uint16_t * Npd, uint16_t * N_OFFSET_CQI, int *H) { - // if FDD return dummy value - if (ccP->tdd_Config == NULL) - return(0); - - switch (ccP->tdd_Config->subframeAssignment) { - case 1: - switch (subframeP) { - case 0: - case 4: - case 5: - case 9: - return(0); - break; - - case 2: - case 3: - case 7: - case 8: - return(1); - break; - - default: - return(0); - break; + uint16_t cqi_PMI_ConfigIndex = + cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex; + uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 }; + + AssertFatal(cqi_ReportPeriodic != NULL, + "cqi_ReportPeriodic is null!\n"); + + if (cc->tdd_Config == NULL) { //FDD + if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period + *Npd = 2; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex; + } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period + *Npd = 5; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 2; + } else if (cqi_PMI_ConfigIndex <= 16) { // 10ms CQI_PMI period + *Npd = 10; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 7; + } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period + *Npd = 20; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 17; + } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period + *Npd = 40; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 37; + } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period + *Npd = 80; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 77; + } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period + *Npd = 160; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 157; + } else if (cqi_PMI_ConfigIndex > 317) { + + if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period + *Npd = 32; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 318; + } else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period + *Npd = 64; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 350; + } else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period + *Npd = 128; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 414; + } + } + } else { // TDD + if (cqi_PMI_ConfigIndex == 0) { // all UL subframes + *Npd = 1; + *N_OFFSET_CQI = 0; + } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period + *Npd = 5; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 1; + } else if (cqi_PMI_ConfigIndex <= 16) { // 10ms CQI_PMI period + *Npd = 10; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 6; + } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period + *Npd = 20; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 16; + } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period + *Npd = 40; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 36; + } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period + *Npd = 80; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 76; + } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period + *Npd = 160; + *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 156; + } } - break; - - case 3: - if ((subframeP<=1) || (subframeP>=5)) - return(0); - else if ((subframeP>1) && (subframeP < 5)) - return(1); - else AssertFatal(1==0,"Unknown subframe number\n"); - break; - - case 4: - if ((subframeP<=1) || (subframeP>=4)) - return(0); - else if ((subframeP>1) && (subframeP < 4)) - return(1); - else AssertFatal(1==0,"Unknown subframe number\n"); - break; - - case 5: - if ((subframeP<=1) || (subframeP>=3)) - return(0); - else if ((subframeP>1) && (subframeP < 3)) - return(1); - else AssertFatal(1==0,"Unknown subframe number\n"); - break; - default: - AssertFatal(1==0,"subframe %d Unsupported TDD configuration %d\n", - subframeP,(int)ccP->tdd_Config->subframeAssignment); - break; - } + // get H + if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic. + present == + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) + *H = 1 + + (Jtab[cc->mib->message.dl_Bandwidth] * + cqi_ReportPeriodic->choice.setup. + cqi_FormatIndicatorPeriodic.choice.subbandCQI.k); + else + *H = 1; } -uint16_t get_pucch1_absSF(COMMON_channels_t *cc,uint16_t dlsch_absSF) +uint8_t +get_dl_cqi_pmi_size_pusch(COMMON_channels_t * cc, uint8_t tmode, + uint8_t ri, + CQI_ReportModeAperiodic_t * + cqi_ReportModeAperiodic) { - uint16_t sf,f,nextf; - - if (cc->tdd_Config==NULL) { //FDD n+4 - return((dlsch_absSF + 4)%10240); - } - else { - sf = dlsch_absSF%10; - f = dlsch_absSF/10; - nextf = (f+1)&1023; + int Ntab[6] = { 0, 4, 7, 9, 10, 13 }; + int N = Ntab[cc->mib->message.dl_Bandwidth]; + int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 }; + int L = Ltab_uesel[cc->mib->message.dl_Bandwidth]; + + AssertFatal(cqi_ReportModeAperiodic != NULL, + "cqi_ReportPeriodic is null!\n"); + + switch (*cqi_ReportModeAperiodic) { + case CQI_ReportModeAperiodic_rm12: + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm12\n", + tmode); + AssertFatal(cc->p_eNB <= 4, + "only up to 4 antenna ports supported here\n"); + if (ri == 1 && cc->p_eNB == 2) + return (4 + (N << 1)); + else if (ri == 2 && cc->p_eNB == 2) + return (8 + N); + else if (ri == 1 && cc->p_eNB == 4) + return (4 + (N << 2)); + else if (ri > 1 && cc->p_eNB == 4) + return (8 + (N << 2)); + break; + case CQI_ReportModeAperiodic_rm20: + // Table 5.2.2.6.3-1 (36.212) + AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7 + || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm20\n", + tmode); + AssertFatal(tmode != 9 + && tmode != 10, + "TM9/10 will be handled later for CQI_ReportModeAperiodic_rm20\n"); + return (4 + 2 + L); + break; + case CQI_ReportModeAperiodic_rm22: + // Table 5.2.2.6.3-2 (36.212) + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm22\n", + tmode); + AssertFatal(tmode != 9 + && tmode != 10, + "TM9/10 will be handled later for CQI_ReportModeAperiodic_rm22\n"); + if (ri == 1 && cc->p_eNB == 2) + return (4 + 2 + 0 + 0 + L + 4); + if (ri == 2 && cc->p_eNB == 2) + return (4 + 2 + 4 + 2 + L + 2); + if (ri == 1 && cc->p_eNB == 4) + return (4 + 2 + 0 + 0 + L + 8); + if (ri >= 2 && cc->p_eNB == 4) + return (4 + 2 + 4 + 2 + L + 8); + break; + case CQI_ReportModeAperiodic_rm30: + // Table 5.2.2.6.2-1 (36.212) + AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7 + || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm30\n", + tmode); + AssertFatal(tmode != 8 && tmode != 9 + && tmode != 10, + "TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm30\n"); + return (4 + (N << 1)); + break; + case CQI_ReportModeAperiodic_rm31: + // Table 5.2.2.6.2-2 (36.212) + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm31\n", + tmode); + AssertFatal(tmode != 8 && tmode != 9 + && tmode != 10, + "TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm31\n"); + if (ri == 1 && cc->p_eNB == 2) + return (4 + (N << 1) + 0 + 0 + 2); + else if (ri == 2 && cc->p_eNB == 2) + return (4 + (N << 1) + 4 + (N << 1) + 1); + else if (ri == 1 && cc->p_eNB == 4) + return (4 + (N << 1) + 0 + 0 + 4); + else if (ri >= 2 && cc->p_eNB == 4) + return (4 + (N << 1) + 4 + (N << 1) + 4); + break; + case CQI_ReportModeAperiodic_rm32_v1250: + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm32\n", + tmode); + AssertFatal(1 == 0, + "CQI_ReportModeAperiodic_rm32_v1250 not supported yet\n"); + break; + case CQI_ReportModeAperiodic_rm10_v1310: + // Table 5.2.2.6.1-1F/G (36.212) + if (ri == 1) + return (4); // F + else + return (7); // G + break; + case CQI_ReportModeAperiodic_rm11_v1310: + // Table 5.2.2.6.1-1H (36.212) + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal TM (%d) for CQI_ReportModeAperiodic_rm11\n", + tmode); + AssertFatal(cc->p_eNB <= 4, + "only up to 4 antenna ports supported here\n"); + if (ri == 1 && cc->p_eNB == 2) + return (4 + 0 + 2); + else if (ri == 2 && cc->p_eNB == 2) + return (4 + 4 + 1); + else if (ri == 1 && cc->p_eNB == 4) + return (4 + 0 + 4); + else if (ri > 1 && cc->p_eNB == 4) + return (4 + 4 + 4); + + break; + } + AssertFatal(1 == 0, "Shouldn't get here\n"); + return (0); +} - switch (cc->tdd_Config->subframeAssignment) { - case 0: - AssertFatal(1==0,"SFA 0 to be filled in now, :-)\n"); - break; +uint8_t +get_rel8_dl_cqi_pmi_size(UE_sched_ctrl * sched_ctl, int CC_idP, + COMMON_channels_t * cc, uint8_t tmode, + struct CQI_ReportPeriodic * cqi_ReportPeriodic) +{ + int no_pmi = 0; + // Ltab[6] = {0,log2(15/4/2),log2(25/4/2),log2(50/6/3),log2(75/8/4),log2(100/8/4)}; + + uint8_t Ltab[6] = { 0, 1, 2, 2, 2, 2 }; + uint8_t ri = sched_ctl->periodic_ri_received[CC_idP]; + + AssertFatal(cqi_ReportPeriodic != NULL, + "cqi_ReportPeriodic is null!\n"); + AssertFatal(cqi_ReportPeriodic->present != + CQI_ReportPeriodic_PR_NOTHING, + "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n"); + AssertFatal(cqi_ReportPeriodic->choice. + setup.cqi_FormatIndicatorPeriodic.present != + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING, + "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n"); + + switch (tmode) { case 1: - if ((sf==5) || (sf==6)) return((10*nextf) + 2); // ACK/NAK in SF 2 next frame - else if (sf==9) return((10*nextf) + 3); // ACK/NAK in SF 3 next frame - else if ((sf==0) || (sf==1)) return((10*f) + 2); // ACK/NAK in SF 7 same frame - else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf); - break; case 2: - if ((sf==4) || (sf==5) || (sf==6) || (sf==8)) return((10*nextf) + 2); // ACK/NAK in SF 2 next frame - else if (sf==9) return((10*nextf) + 7); // ACK/NAK in SF 7 next frame - else if ((sf==0) || (sf==1) || (sf==3)) return((10*f) + 7); // ACK/NAK in SF 7 same frame - else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf); - break; - case 3: - if ((sf==5) || (sf==6) || (sf==7) || (sf==8) || (sf==9)) return((10*nextf) + (sf>>1)); // ACK/NAK in 2,3,4 resp. next frame - else if (sf==1) return((10*nextf) + 2); // ACK/NAK in 2 next frame - else if (sf==0) return((10*f) + 4); // ACK/NAK in 4 same frame - else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf); - break; - case 4: - if ((sf==6) || (sf==7) || (sf==8) || (sf==9)) return(((10*nextf) + 3)%10240); // ACK/NAK in SF 3 next frame - else if ((sf==0) || (sf==1) || (sf==4) || (sf==5)) return(((10*nextf) + 2)%10240); // ACK/NAK in SF 2 next frame - else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 4\n",sf); - break; case 5: - if ((sf==0) || (sf==1) || (sf==3) || (sf==4) || (sf==5) || (sf==6) || (sf==7) || (sf==8)) return(((10*nextf) + 2)%10240); // ACK/NAK in SF 3 next frame - else if (sf==9) return(((10*(1+nextf)) + 2)%10240); // ACK/NAK in SF 2 next frame - else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 5\n",sf); - break; case 6: - AssertFatal(1==0,"SFA 6 To be filled in now, :-)\n"); - break; + case 7: + no_pmi = 1; + break; default: - AssertFatal(1==0,"Illegal TDD subframe Assigment %d\n",(int)cc->tdd_Config->subframeAssignment); - break; - } - } - AssertFatal(1==0,"Shouldn't get here\n"); -} - -void get_srs_pos(COMMON_channels_t *cc,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset) -{ - if(cc->tdd_Config) { // TDD - AssertFatal(isrs>=10,"2 ms SRS periodicity not supported"); - - if ((isrs>9)&&(isrs<15)) { - *psrsPeriodicity=5; - *psrsOffset=isrs-10; - } - if ((isrs>14)&&(isrs<25)) { - *psrsPeriodicity=10; - *psrsOffset=isrs-15; - } - if ((isrs>24)&&(isrs<45)) { - *psrsPeriodicity=20; - *psrsOffset=isrs-25; - } - if ((isrs>44)&&(isrs<85)) { - *psrsPeriodicity=40; - *psrsOffset=isrs-45; - } - if ((isrs>84)&&(isrs<165)) { - *psrsPeriodicity=80; - *psrsOffset=isrs-85; - } - if ((isrs>164)&&(isrs<325)) { - *psrsPeriodicity=160; - *psrsOffset=isrs-165; - } - if ((isrs>324)&&(isrs<645)) { - *psrsPeriodicity=320; - *psrsOffset=isrs-325; - } - - AssertFatal(isrs<=644,"Isrs out of range %d>644\n",isrs); - } // TDD - else { // FDD - if (isrs<2) { - *psrsPeriodicity=2; - *psrsOffset=isrs; - } - if ((isrs>1)&&(isrs<7)) { - *psrsPeriodicity=5; - *psrsOffset=isrs-2; - } - if ((isrs>6)&&(isrs<17)) { - *psrsPeriodicity=10; - *psrsOffset=isrs-7; - } - if ((isrs>16)&&(isrs<37)) { - *psrsPeriodicity=20; - *psrsOffset=isrs-17; + no_pmi = 0; } - if ((isrs>36)&&(isrs<77)) { - *psrsPeriodicity=40; - *psrsOffset=isrs-37; - } - if ((isrs>76)&&(isrs<157)) { - *psrsPeriodicity=80; - *psrsOffset=isrs-77; - } - if ((isrs>156)&&(isrs<317)) { - *psrsPeriodicity=160; - *psrsOffset=isrs-157; - } - if ((isrs>316)&&(isrs<637)) { - *psrsPeriodicity=320; - *psrsOffset=isrs-317; - } - AssertFatal(isrs<=636,"Isrs out of range %d>636\n",isrs); - } -} - -void get_csi_params(COMMON_channels_t *cc,struct CQI_ReportPeriodic *cqi_ReportPeriodic,uint16_t *Npd,uint16_t *N_OFFSET_CQI,int *H) -{ - uint16_t cqi_PMI_ConfigIndex = cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex; - uint8_t Jtab[6] = {0,2,2,3,4,4}; - - AssertFatal(cqi_ReportPeriodic!=NULL,"cqi_ReportPeriodic is null!\n"); - - if (cc->tdd_Config==NULL) { //FDD - if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period - *Npd = 2; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex; - } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period - *Npd = 5; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-2; - } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period - *Npd = 10; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-7; - } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period - *Npd = 20; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-17; - } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period - *Npd = 40; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-37; - } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period - *Npd = 80; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-77; - } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period - *Npd = 160; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-157; - } - else if (cqi_PMI_ConfigIndex > 317) { - if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period - *Npd = 32; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-318; - } - else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period - *Npd = 64; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-350; - } - else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period - *Npd = 128; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-414; - } + if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic. + present == + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) + || (sched_ctl->feedback_cnt[CC_idP] == 0)) { + // send wideband report every opportunity if wideband reporting mode is selected, else every H opportunities + if (no_pmi == 1) + return (4); + else if ((cc->p_eNB == 2) && (ri == 1)) + return (6); + else if ((cc->p_eNB == 2) && (ri == 2)) + return (8); + else if ((cc->p_eNB == 4) && (ri == 1)) + return (8); + else if ((cc->p_eNB == 4) && (ri == 2)) + return (11); + else + AssertFatal(1 == 0, + "illegal combination p %d, ri %d, no_pmi %d\n", + cc->p_eNB, ri, no_pmi); + } else if (cqi_ReportPeriodic->choice. + setup.cqi_FormatIndicatorPeriodic.present == + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) + { + if ((no_pmi == 1) || ri == 1) + return (4 + Ltab[cc->mib->message.dl_Bandwidth]); + else + return (7 + Ltab[cc->mib->message.dl_Bandwidth]); } - } - else { // TDD - if (cqi_PMI_ConfigIndex == 0) { // all UL subframes - *Npd = 1; - *N_OFFSET_CQI = 0; - } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period - *Npd = 5; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-1; - } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period - *Npd = 10; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-6; - } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period - *Npd = 20; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-16; - } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period - *Npd = 40; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-36; - } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period - *Npd = 80; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-76; - } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period - *Npd = 160; - *N_OFFSET_CQI = cqi_PMI_ConfigIndex-156; - } - } - - // get H - if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) - *H = 1+(Jtab[cc->mib->message.dl_Bandwidth]*cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.choice.subbandCQI.k); - else - *H=1; + AssertFatal(1 == 0, + "Shouldn't get here : cqi_ReportPeriodic->present %d\n", + cqi_ReportPeriodic->choice. + setup.cqi_FormatIndicatorPeriodic.present); } -uint8_t get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc,uint8_t tmode,uint8_t ri, CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic) +void +fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t * dl_config_pdu, + uint8_t aggregation_level, + uint16_t rnti, + uint8_t rnti_type, + uint8_t harq_process, + uint8_t tpc, + uint16_t resource_block_coding, + uint8_t mcs, uint8_t ndi, uint8_t rv, + uint8_t vrb_flag) { - int Ntab[6] = {0,4,7,9,10,13}; - int N = Ntab[cc->mib->message.dl_Bandwidth]; - int Ltab_uesel[6] = {0,6,9,13,15,18}; - int L = Ltab_uesel[cc->mib->message.dl_Bandwidth]; - - AssertFatal(cqi_ReportModeAperiodic != NULL,"cqi_ReportPeriodic is null!\n"); - - switch (*cqi_ReportModeAperiodic) { - case CQI_ReportModeAperiodic_rm12: - AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm12\n",tmode); - AssertFatal(cc->p_eNB<=4,"only up to 4 antenna ports supported here\n"); - if (ri==1 && cc->p_eNB==2) return(4+(N<<1)); - else if (ri==2 && cc->p_eNB==2) return(8+N); - else if (ri==1 && cc->p_eNB==4) return(4+(N<<2)); - else if (ri>1 && cc->p_eNB==4) return(8+(N<<2)); - break; - case CQI_ReportModeAperiodic_rm20: - // Table 5.2.2.6.3-1 (36.212) - AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm20\n",tmode); - AssertFatal(tmode!=9 && tmode!=10,"TM9/10 will be handled later for CQI_ReportModeAperiodic_rm20\n"); - return(4+2+L); - break; - case CQI_ReportModeAperiodic_rm22: - // Table 5.2.2.6.3-2 (36.212) - AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm22\n",tmode); - AssertFatal(tmode!=9 && tmode!=10,"TM9/10 will be handled later for CQI_ReportModeAperiodic_rm22\n"); - if (ri==1 && cc->p_eNB==2) return(4+2+0+0+L+4); - if (ri==2 && cc->p_eNB==2) return(4+2+4+2+L+2); - if (ri==1 && cc->p_eNB==4) return(4+2+0+0+L+8); - if (ri>=2 && cc->p_eNB==4) return(4+2+4+2+L+8); - break; - case CQI_ReportModeAperiodic_rm30: - // Table 5.2.2.6.2-1 (36.212) - AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm30\n",tmode); - AssertFatal(tmode!=8 && tmode!=9 && tmode!=10,"TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm30\n"); - return(4+(N<<1)); - break; - case CQI_ReportModeAperiodic_rm31: - // Table 5.2.2.6.2-2 (36.212) - AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm31\n",tmode); - AssertFatal(tmode!=8 && tmode!=9 && tmode!=10,"TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm31\n"); - if (ri==1 && cc->p_eNB==2) return(4+(N<<1)+0+0+2); - else if (ri==2 && cc->p_eNB==2) return(4+(N<<1)+4+(N<<1)+1); - else if (ri==1 && cc->p_eNB==4) return(4+(N<<1)+0+0+4); - else if (ri>=2 && cc->p_eNB==4) return(4+(N<<1)+4+(N<<1)+4); - break; - case CQI_ReportModeAperiodic_rm32_v1250: - AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm32\n",tmode); - AssertFatal(1==0,"CQI_ReportModeAperiodic_rm32_v1250 not supported yet\n"); - break; - case CQI_ReportModeAperiodic_rm10_v1310: - // Table 5.2.2.6.1-1F/G (36.212) - if (ri==1) return(4); // F - else return(7); // G - break; - case CQI_ReportModeAperiodic_rm11_v1310: - // Table 5.2.2.6.1-1H (36.212) - AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm11\n",tmode); - AssertFatal(cc->p_eNB<=4,"only up to 4 antenna ports supported here\n"); - if (ri==1 && cc->p_eNB==2) return(4+0+2); - else if (ri==2 && cc->p_eNB==2) return(4+4+1); - else if (ri==1 && cc->p_eNB==4) return(4+0+4); - else if (ri>1 && cc->p_eNB==4) return(4+4+4); - - break; - } - AssertFatal(1==0,"Shouldn't get here\n"); - return(0); + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = + NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + aggregation_level; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = rnti_type; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_process; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = + resource_block_coding; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ndi; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = rv; + dl_config_pdu->dci_dl_pdu. + dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = vrb_flag; } -uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl *sched_ctl,int CC_idP,COMMON_channels_t *cc,uint8_t tmode, struct CQI_ReportPeriodic *cqi_ReportPeriodic) +void +program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP, + frame_t frameP, sub_frame_t subframeP, + uint8_t cce_idx) { - int no_pmi=0; - // Ltab[6] = {0,log2(15/4/2),log2(25/4/2),log2(50/6/3),log2(75/8/4),log2(100/8/4)}; - - uint8_t Ltab[6] = {0,1,2,2,2,2}; - uint8_t ri = sched_ctl->periodic_ri_received[CC_idP]; - - AssertFatal(cqi_ReportPeriodic != NULL,"cqi_ReportPeriodic is null!\n"); - AssertFatal(cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_NOTHING, - "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n"); - AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING, - "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n"); - - switch(tmode) { - case 1: - case 2: - case 5: - case 6: - case 7: - no_pmi=1; - break; - default: - no_pmi=0; - } + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = eNB->common_channels; + UE_list_t *UE_list = &eNB->UE_list; + rnti_t rnti = UE_RNTI(module_idP, UE_idP); + nfapi_ul_config_request_body_t *ul_req; + nfapi_ul_config_request_pdu_t *ul_config_pdu; - if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) || - (sched_ctl->feedback_cnt[CC_idP] == 0)) { - // send wideband report every opportunity if wideband reporting mode is selected, else every H opportunities - if (no_pmi == 1) - return(4); - else if ((cc->p_eNB==2) && (ri==1)) return(6); - else if ((cc->p_eNB==2) && (ri==2)) return(8); - else if ((cc->p_eNB==4) && (ri==1)) return(8); - else if ((cc->p_eNB==4) && (ri==2)) return(11); - else AssertFatal(1==0,"illegal combination p %d, ri %d, no_pmi %d\n",cc->p_eNB,ri,no_pmi); - } - else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) { - if ((no_pmi == 1)||ri==1) return(4+Ltab[cc->mib->message.dl_Bandwidth]); - else - return(7+Ltab[cc->mib->message.dl_Bandwidth]); - } - AssertFatal(1==0,"Shouldn't get here : cqi_ReportPeriodic->present %d\n",cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present); -} - -void fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t *dl_config_pdu, - uint8_t aggregation_level, - uint16_t rnti, - uint8_t rnti_type, - uint8_t harq_process, - uint8_t tpc, - uint16_t resource_block_coding, - uint8_t mcs, - uint8_t ndi, - uint8_t rv, - uint8_t vrb_flag) -{ - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation_level; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = rnti_type; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_process; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = resource_block_coding; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ndi; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = rv; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = vrb_flag; -} - -void program_dlsch_acknak(module_id_t module_idP, int CC_idP,int UE_idP, frame_t frameP, sub_frame_t subframeP,uint8_t cce_idx) -{ - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; - rnti_t rnti = UE_RNTI(module_idP,UE_idP); - nfapi_ul_config_request_body_t *ul_req; - nfapi_ul_config_request_pdu_t *ul_config_pdu; - - int use_simultaneous_pucch_pusch=0; - nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = NULL; - nfapi_ul_config_harq_information *harq_information = NULL; + int use_simultaneous_pucch_pusch = 0; + nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = NULL; + nfapi_ul_config_harq_information *harq_information = NULL; #if defined(Rel10) || defined(Rel14) - if ((UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2) && - (UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020) && - (UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10) && - (*UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10 == - PUCCH_ConfigDedicated_v1020__simultaneousPUCCH_PUSCH_r10_true)) - use_simultaneous_pucch_pusch=1; + if ((UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated-> + ext2) + && (UE_list->UE_template[CC_idP][UE_idP]. + physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020) + && (UE_list->UE_template[CC_idP][UE_idP]. + physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020-> + simultaneousPUCCH_PUSCH_r10) + && (*UE_list->UE_template[CC_idP][UE_idP]. + physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020-> + simultaneousPUCCH_PUSCH_r10 == + PUCCH_ConfigDedicated_v1020__simultaneousPUCCH_PUSCH_r10_true)) + use_simultaneous_pucch_pusch = 1; #endif - // pucch1 and pusch feedback is similar, namely in n+k subframes from now - // This is used in the following "if/else" condition to check if there isn't or is already an UL grant in n+k - int16_t ul_absSF = get_pucch1_absSF(&cc[CC_idP],subframeP+(10*frameP)); - - if ((ul_config_pdu = has_ul_grant(module_idP,CC_idP, - ul_absSF, - rnti)) == NULL) { - // no UL grant so - // Program ACK/NAK alone Format 1a/b or 3 - - ul_req = &RC.mac[module_idP]->UL_req_tmp[CC_idP][ul_absSF%10].ul_config_request_body; - ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - // Do PUCCH - fill_nfapi_uci_acknak(module_idP, - CC_idP, - rnti, - (frameP*10)+subframeP, - cce_idx); - } - else { - /* there is already an existing UL grant so update it if needed - * on top of some other UL resource (PUSCH,combined SR/CQI/HARQ on PUCCH, etc) - */ - switch(ul_config_pdu->pdu_type) { - - /* [ulsch] to [ulsch + harq] or [ulsch + harq on pucch] */ - - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - if (use_simultaneous_pucch_pusch==1) { - // Convert it to an NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE - harq_information = &ul_config_pdu->ulsch_uci_harq_pdu.harq_information; - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE; - LOG_D(MAC,"Frame %d, Subframe %d: Switched UCI HARQ to ULSCH UCI HARQ\n",frameP,subframeP); - } - else { - // Convert it to an NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE - ulsch_harq_information = &ul_config_pdu->ulsch_harq_pdu.harq_information; - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; - ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial=0; // last symbol not punctured - ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks= - ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks; // we don't change the number of resource blocks across retransmissions yet - LOG_D(MAC,"Frame %d, Subframe %d: Switched UCI HARQ to ULSCH HARQ\n",frameP,subframeP); - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - AssertFatal(use_simultaneous_pucch_pusch == 1, - "Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active"); - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - AssertFatal(use_simultaneous_pucch_pusch == 0, - "Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n"); - break; - - /* [ulsch + cqi] to [ulsch + cqi + harq] */ - - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - // Convert it to an NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE - ulsch_harq_information = &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information; - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; - /* TODO: check this - when converting from nfapi_ul_config_ulsch_cqi_ri_pdu to - * nfapi_ul_config_ulsch_cqi_harq_ri_pdu, shouldn't we copy initial_transmission_parameters - * from the one to the other? - * Those two types are not compatible. 'initial_transmission_parameters' is not at the - * place in both. - */ - ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial=0; // last symbol not punctured - ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks= - ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks; // we don't change the number of resource blocks across retransmissions yet - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - AssertFatal(use_simultaneous_pucch_pusch == 0, - "Cannot be NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE, simultaneous_pucch_pusch is active\n"); - break; - - /* [ulsch + cqi on pucch] to [ulsch + cqi on pucch + harq on pucch] */ - - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - // convert it to an NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE - harq_information = &ul_config_pdu->ulsch_csi_uci_harq_pdu.harq_information; - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE; - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - AssertFatal(use_simultaneous_pucch_pusch == 1, - "Cannot be NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE, simultaneous_pucch_pusch is inactive\n"); - break; - - /* [sr] to [sr + harq] */ - - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - // convert to NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE; - harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information; - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - /* nothing to do */ - break; - - /* [cqi] to [cqi + harq] */ - - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - // convert to NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE; - harq_information = &ul_config_pdu->uci_cqi_harq_pdu.harq_information; - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - /* nothing to do */ - break; - - /* [cqi + sr] to [cqr + sr + harq] */ - - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - // convert to NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE; - harq_information = &ul_config_pdu->uci_cqi_sr_harq_pdu.harq_information; - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - /* nothing to do */ - break; + // pucch1 and pusch feedback is similar, namely in n+k subframes from now + // This is used in the following "if/else" condition to check if there isn't or is already an UL grant in n+k + int16_t ul_absSF = + get_pucch1_absSF(&cc[CC_idP], subframeP + (10 * frameP)); + + if ((ul_config_pdu = has_ul_grant(module_idP, CC_idP, + ul_absSF, rnti)) == NULL) { + // no UL grant so + // Program ACK/NAK alone Format 1a/b or 3 + + ul_req = + &RC.mac[module_idP]->UL_req_tmp[CC_idP][ul_absSF % + 10]. + ul_config_request_body; + ul_config_pdu = + &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; + // Do PUCCH + fill_nfapi_uci_acknak(module_idP, + CC_idP, + rnti, (frameP * 10) + subframeP, cce_idx); + } else { + /* there is already an existing UL grant so update it if needed + * on top of some other UL resource (PUSCH,combined SR/CQI/HARQ on PUCCH, etc) + */ + switch (ul_config_pdu->pdu_type) { + + /* [ulsch] to [ulsch + harq] or [ulsch + harq on pucch] */ + + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: + if (use_simultaneous_pucch_pusch == 1) { + // Convert it to an NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE + harq_information = + &ul_config_pdu->ulsch_uci_harq_pdu.harq_information; + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE; + LOG_D(MAC, + "Frame %d, Subframe %d: Switched UCI HARQ to ULSCH UCI HARQ\n", + frameP, subframeP); + } else { + // Convert it to an NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE + ulsch_harq_information = + &ul_config_pdu->ulsch_harq_pdu.harq_information; + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; + ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks; // we don't change the number of resource blocks across retransmissions yet + LOG_D(MAC, + "Frame %d, Subframe %d: Switched UCI HARQ to ULSCH HARQ\n", + frameP, subframeP); + } + break; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: + AssertFatal(use_simultaneous_pucch_pusch == 1, + "Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active"); + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: + AssertFatal(use_simultaneous_pucch_pusch == 0, + "Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n"); + break; + + /* [ulsch + cqi] to [ulsch + cqi + harq] */ + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: + // Convert it to an NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE + ulsch_harq_information = + &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information; + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; + /* TODO: check this - when converting from nfapi_ul_config_ulsch_cqi_ri_pdu to + * nfapi_ul_config_ulsch_cqi_harq_ri_pdu, shouldn't we copy initial_transmission_parameters + * from the one to the other? + * Those two types are not compatible. 'initial_transmission_parameters' is not at the + * place in both. + */ + ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks; // we don't change the number of resource blocks across retransmissions yet + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: + AssertFatal(use_simultaneous_pucch_pusch == 0, + "Cannot be NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE, simultaneous_pucch_pusch is active\n"); + break; + + /* [ulsch + cqi on pucch] to [ulsch + cqi on pucch + harq on pucch] */ + + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: + // convert it to an NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE + harq_information = + &ul_config_pdu->ulsch_csi_uci_harq_pdu.harq_information; + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE; + break; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: + AssertFatal(use_simultaneous_pucch_pusch == 1, + "Cannot be NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE, simultaneous_pucch_pusch is inactive\n"); + break; + + /* [sr] to [sr + harq] */ + + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: + // convert to NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE; + harq_information = + &ul_config_pdu->uci_sr_harq_pdu.harq_information; + break; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: + /* nothing to do */ + break; + + /* [cqi] to [cqi + harq] */ + + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: + // convert to NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE; + harq_information = + &ul_config_pdu->uci_cqi_harq_pdu.harq_information; + break; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: + /* nothing to do */ + break; + + /* [cqi + sr] to [cqr + sr + harq] */ + + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: + // convert to NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE + ul_config_pdu->pdu_type = + NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE; + harq_information = + &ul_config_pdu->uci_cqi_sr_harq_pdu.harq_information; + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: + /* nothing to do */ + break; + } } - } - if (ulsch_harq_information) fill_nfapi_ulsch_harq_information(module_idP,CC_idP, - rnti, - ulsch_harq_information); + if (ulsch_harq_information) + fill_nfapi_ulsch_harq_information(module_idP, CC_idP, + rnti, ulsch_harq_information); - if (harq_information) fill_nfapi_harq_information(module_idP,CC_idP, - rnti, - (frameP*10)+subframeP, - harq_information, - cce_idx); + if (harq_information) + fill_nfapi_harq_information(module_idP, CC_idP, + rnti, + (frameP * 10) + subframeP, + harq_information, cce_idx); } -uint8_t get_V_UL_DAI(module_id_t module_idP,int CC_idP,uint16_t rntiP) +uint8_t get_V_UL_DAI(module_id_t module_idP, int CC_idP, uint16_t rntiP) { - nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[0]; + nfapi_hi_dci0_request_body_t *HI_DCI0_req = + &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = + &HI_DCI0_req->hi_dci0_pdu_list[0]; + + for (int i = 0; i < HI_DCI0_req->number_of_dci; i++) { + if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) && + (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP)) + return (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8. + dl_assignment_index); + } + return (4); // this is rule from Section 7.3 in 36.213 +} - for (int i=0;i<HI_DCI0_req->number_of_dci;i++) { - if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)&& - (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP)) - return(hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index); - } - return(4); // this is rule from Section 7.3 in 36.213 +void +fill_nfapi_ulsch_harq_information(module_id_t module_idP, + int CC_idP, + uint16_t rntiP, + nfapi_ul_config_ulsch_harq_information + * harq_information) +{ + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; + UE_list_t *UE_list = &eNB->UE_list; + + int UE_id = find_UE_id(module_idP, rntiP); + + PUSCH_ConfigDedicated_t *puschConfigDedicated; + // PUSCH_ConfigDedicated_v1020_t *puschConfigDedicated_v1020; + // PUSCH_ConfigDedicated_v1130_t *puschConfigDedicated_v1130; + // PUSCH_ConfigDedicated_v1250_t *puschConfigDedicated_v1250; + + AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); + AssertFatal(UE_list != NULL, "UE_list is null\n"); + AssertFatal(UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated != NULL, + "physicalConfigDedicated for rnti %x is null\n", rntiP); + AssertFatal((puschConfigDedicated = (PUSCH_ConfigDedicated_t *) + UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated->pusch_ConfigDedicated) != NULL, + "physicalConfigDedicated->puschConfigDedicated for rnti %x is null\n", + rntiP); +#if defined(Rel14) || defined(Rel14) + /* if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2) puschConfigDedicated_v1020 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2->pusch_ConfigDedicated_v1020; + #endif + #ifdef Rel14 + if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4) puschConfigDedicated_v1130 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4->pusch_ConfigDedicated_v1130; + if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5) puschConfigDedicated_v1250 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5->pusch_ConfigDedicated_v1250; + */ +#endif + harq_information->harq_information_rel10.delta_offset_harq = + puschConfigDedicated->betaOffset_ACK_Index; + AssertFatal(UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated != NULL, + "pucch_ConfigDedicated is null!\n"); + if ((UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated->pucch_ConfigDedicated-> + tdd_AckNackFeedbackMode != NULL) + && (*UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated->pucch_ConfigDedicated-> + tdd_AckNackFeedbackMode == + PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) + harq_information->harq_information_rel10.ack_nack_mode = 1; // multiplexing + else + harq_information->harq_information_rel10.ack_nack_mode = 0; // bundling + + switch (get_tmode(module_idP, CC_idP, UE_id)) { + case 1: + case 2: + case 5: + case 6: + case 7: + if (cc->tdd_Config == NULL) // FDD + harq_information->harq_information_rel10.harq_size = 1; + else { + if (harq_information->harq_information_rel10.ack_nack_mode == + 1) + harq_information->harq_information_rel10.harq_size = + get_V_UL_DAI(module_idP, CC_idP, rntiP); + else + harq_information->harq_information_rel10.harq_size = 1; + } + break; + default: // for any other TM we need 2 bits harq + if (cc->tdd_Config == NULL) { + harq_information->harq_information_rel10.harq_size = 2; + } else { + if (harq_information->harq_information_rel10.ack_nack_mode == + 1) + harq_information->harq_information_rel10.harq_size = + get_V_UL_DAI(module_idP, CC_idP, rntiP); + else + harq_information->harq_information_rel10.harq_size = 2; + } + break; + } // get Tmode } -void fill_nfapi_ulsch_harq_information(module_id_t module_idP, - int CC_idP, - uint16_t rntiP, - nfapi_ul_config_ulsch_harq_information *harq_information) +void +fill_nfapi_harq_information(module_id_t module_idP, + int CC_idP, + uint16_t rntiP, + uint16_t absSFP, + nfapi_ul_config_harq_information * + harq_information, uint8_t cce_idxP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; + UE_list_t *UE_list = &eNB->UE_list; - int UE_id = find_UE_id(module_idP,rntiP); + int UE_id = find_UE_id(module_idP, rntiP); - PUSCH_ConfigDedicated_t *puschConfigDedicated; - // PUSCH_ConfigDedicated_v1020_t *puschConfigDedicated_v1020; - // PUSCH_ConfigDedicated_v1130_t *puschConfigDedicated_v1130; - // PUSCH_ConfigDedicated_v1250_t *puschConfigDedicated_v1250; + AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); + AssertFatal(UE_list != NULL, "UE_list is null\n"); + AssertFatal(UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated != NULL, + "physicalConfigDedicated for rnti %x is null\n", rntiP); - AssertFatal(UE_id>=0,"UE_id cannot be found, impossible\n"); - AssertFatal(UE_list!=NULL,"UE_list is null\n"); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated for rnti %x is null\n",rntiP); - AssertFatal((puschConfigDedicated = (PUSCH_ConfigDedicated_t *)UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pusch_ConfigDedicated)!=NULL,"physicalConfigDedicated->puschConfigDedicated for rnti %x is null\n",rntiP); -#if defined(Rel14) || defined(Rel14) - /* if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2) puschConfigDedicated_v1020 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2->pusch_ConfigDedicated_v1020; -#endif -#ifdef Rel14 - if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4) puschConfigDedicated_v1130 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4->pusch_ConfigDedicated_v1130; - if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5) puschConfigDedicated_v1250 = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5->pusch_ConfigDedicated_v1250; - */ -#endif - harq_information->harq_information_rel10.delta_offset_harq = puschConfigDedicated->betaOffset_ACK_Index; - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,"pucch_ConfigDedicated is null!\n"); - if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&& - (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) - harq_information->harq_information_rel10.ack_nack_mode = 1; // multiplexing - else - harq_information->harq_information_rel10.ack_nack_mode = 0; // bundling - - switch(get_tmode(module_idP,CC_idP,UE_id)) { - case 1: - case 2: - case 5: - case 6: - case 7: - if (cc->tdd_Config==NULL) // FDD - harq_information->harq_information_rel10.harq_size = 1; - else { - if (harq_information->harq_information_rel10.ack_nack_mode == 1) - harq_information->harq_information_rel10.harq_size = get_V_UL_DAI(module_idP,CC_idP,rntiP); - else - harq_information->harq_information_rel10.harq_size = 1; - } - break; - default: // for any other TM we need 2 bits harq - if (cc->tdd_Config==NULL) { - harq_information->harq_information_rel10.harq_size = 2; - } - else { - if (harq_information->harq_information_rel10.ack_nack_mode == 1) - harq_information->harq_information_rel10.harq_size = get_V_UL_DAI(module_idP,CC_idP,rntiP); - else - harq_information->harq_information_rel10.harq_size = 2; - } - break; - } // get Tmode + harq_information->harq_information_rel11.num_ant_ports = 1; + + switch (get_tmode(module_idP, CC_idP, UE_id)) { + case 1: + case 2: + case 5: + case 6: + case 7: + if (cc->tdd_Config != NULL) { + AssertFatal(UE_list-> + UE_template[CC_idP] + [UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated != NULL, + "pucch_ConfigDedicated is null for TDD!\n"); + if ((UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL) + && (*UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated->tdd_AckNackFeedbackMode == + PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) + { + harq_information->harq_information_rel10_tdd.harq_size = 2; // 2-bit ACK/NAK + harq_information->harq_information_rel10_tdd.ack_nack_mode = 1; // multiplexing + } else { + harq_information->harq_information_rel10_tdd.harq_size = 1; // 1-bit ACK/NAK + harq_information->harq_information_rel10_tdd.ack_nack_mode = 0; // bundling + } + harq_information->harq_information_rel10_tdd.n_pucch_1_0 = + cc->radioResourceConfigCommon->pucch_ConfigCommon. + n1PUCCH_AN + cce_idxP; + harq_information-> + harq_information_rel10_tdd.number_of_pucch_resources = 1; + } else { + harq_information-> + harq_information_rel9_fdd.number_of_pucch_resources = 1; + harq_information->harq_information_rel9_fdd.harq_size = 1; // 1-bit ACK/NAK + harq_information->harq_information_rel9_fdd.n_pucch_1_0 = + cc->radioResourceConfigCommon->pucch_ConfigCommon. + n1PUCCH_AN + cce_idxP; + } + break; + default: // for any other TM we need 2 bits harq + if (cc->tdd_Config != NULL) { + AssertFatal(UE_list-> + UE_template[CC_idP] + [UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated != NULL, + "pucch_ConfigDedicated is null for TDD!\n"); + if ((UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL) + && (*UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated->tdd_AckNackFeedbackMode == + PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) + { + harq_information->harq_information_rel10_tdd.ack_nack_mode = 1; // multiplexing + } else { + harq_information->harq_information_rel10_tdd.ack_nack_mode = 0; // bundling + } + harq_information->harq_information_rel10_tdd.harq_size = 2; + harq_information->harq_information_rel10_tdd.n_pucch_1_0 = + cc->radioResourceConfigCommon->pucch_ConfigCommon. + n1PUCCH_AN + cce_idxP; + harq_information-> + harq_information_rel10_tdd.number_of_pucch_resources = 1; + } else { + harq_information-> + harq_information_rel9_fdd.number_of_pucch_resources = 1; + harq_information->harq_information_rel9_fdd.ack_nack_mode = 0; // 1a/b + harq_information->harq_information_rel9_fdd.harq_size = 2; + harq_information->harq_information_rel9_fdd.n_pucch_1_0 = + cc->radioResourceConfigCommon->pucch_ConfigCommon. + n1PUCCH_AN + cce_idxP; + } + break; + } // get Tmode } -void fill_nfapi_harq_information(module_id_t module_idP, - int CC_idP, - uint16_t rntiP, - uint16_t absSFP, - nfapi_ul_config_harq_information *harq_information, - uint8_t cce_idxP) +uint16_t +fill_nfapi_uci_acknak(module_id_t module_idP, + int CC_idP, + uint16_t rntiP, uint16_t absSFP, uint8_t cce_idxP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; - - int UE_id = find_UE_id(module_idP,rntiP); + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; + + int ackNAK_absSF = get_pucch1_absSF(cc, absSFP); + nfapi_ul_config_request_body_t *ul_req = + &eNB->UL_req_tmp[CC_idP][ackNAK_absSF % 10].ul_config_request_body; + nfapi_ul_config_request_pdu_t *ul_config_pdu = + &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; + + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_harq_pdu)); + ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0; // don't know how to use this + ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti = + rntiP; + + fill_nfapi_harq_information(module_idP, CC_idP, + rntiP, + absSFP, + &ul_config_pdu->uci_harq_pdu. + harq_information, cce_idxP); + LOG_D(MAC, + "Filled in UCI HARQ request for rnti %x SF %d.%d acknakSF %d.%d, cce_idxP %d-> n1_pucch %d\n", + rntiP, absSFP / 10, absSFP % 10, ackNAK_absSF / 10, + ackNAK_absSF % 10, cce_idxP, + ul_config_pdu->uci_harq_pdu. + harq_information.harq_information_rel9_fdd.n_pucch_1_0); + + ul_req->number_of_pdus++; + + return (((ackNAK_absSF / 10) << 4) + (ackNAK_absSF % 10)); +} - AssertFatal(UE_id>=0,"UE_id cannot be found, impossible\n"); - AssertFatal(UE_list!=NULL,"UE_list is null\n"); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated for rnti %x is null\n",rntiP); +void +fill_nfapi_dlsch_config(eNB_MAC_INST * eNB, + nfapi_dl_config_request_body_t * dl_req, + uint16_t length, + uint16_t pdu_index, + uint16_t rnti, + uint8_t resource_allocation_type, + uint8_t + virtual_resource_block_assignment_flag, + uint16_t resource_block_coding, + uint8_t modulation, + uint8_t redundancy_version, + uint8_t transport_blocks, + uint8_t transport_block_to_codeword_swap_flag, + uint8_t transmission_scheme, + uint8_t number_of_layers, + uint8_t number_of_subbands, + // uint8_t codebook_index, + uint8_t ue_category_capacity, + uint8_t pa, + uint8_t delta_power_offset_index, + uint8_t ngap, + uint8_t nprb, + uint8_t transmission_mode, + uint8_t num_bf_prb_per_subband, + uint8_t num_bf_vector) +{ + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = length; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = pdu_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = + resource_allocation_type; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.virtual_resource_block_assignment_flag = + virtual_resource_block_assignment_flag; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = + resource_block_coding; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = modulation; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = + redundancy_version; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = + transport_blocks; + dl_config_pdu->dlsch_pdu. + dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = + transport_block_to_codeword_swap_flag; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = + transmission_scheme; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = + number_of_layers; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = + number_of_subbands; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = codebook_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = + ue_category_capacity; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = pa; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = + delta_power_offset_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = ngap; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = nprb; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = + transmission_mode; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = + num_bf_prb_per_subband; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = num_bf_vector; + dl_req->number_pdu++; +} - harq_information->harq_information_rel11.num_ant_ports = 1; +uint16_t +fill_nfapi_tx_req(nfapi_tx_request_body_t * tx_req_body, + uint16_t absSF, uint16_t pdu_length, + uint16_t pdu_index, uint8_t * pdu) +{ + nfapi_tx_request_pdu_t *TX_req = + &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus]; + LOG_D(MAC, "Filling TX_req %d for pdu length %d\n", + tx_req_body->number_of_pdus, pdu_length); + TX_req->pdu_length = pdu_length; + TX_req->pdu_index = pdu_index; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = pdu_length; + TX_req->segments[0].segment_data = pdu; + tx_req_body->number_of_pdus++; + + return (((absSF / 10) << 4) + (absSF % 10)); +} - switch(get_tmode(module_idP,CC_idP,UE_id)) { - case 1: - case 2: - case 5: - case 6: - case 7: - if (cc->tdd_Config!=NULL) { - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL, - "pucch_ConfigDedicated is null for TDD!\n"); - if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&& - (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) { - harq_information->harq_information_rel10_tdd.harq_size = 2; // 2-bit ACK/NAK - harq_information->harq_information_rel10_tdd.ack_nack_mode = 1; // multiplexing - } - else { - harq_information->harq_information_rel10_tdd.harq_size = 1; // 1-bit ACK/NAK - harq_information->harq_information_rel10_tdd.ack_nack_mode = 0; // bundling - } - harq_information->harq_information_rel10_tdd.n_pucch_1_0 = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP; - harq_information->harq_information_rel10_tdd.number_of_pucch_resources = 1; - } else { - harq_information->harq_information_rel9_fdd.number_of_pucch_resources = 1; - harq_information->harq_information_rel9_fdd.harq_size = 1; // 1-bit ACK/NAK - harq_information->harq_information_rel9_fdd.n_pucch_1_0 = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP; - } - break; - default: // for any other TM we need 2 bits harq - if (cc->tdd_Config!=NULL) { - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL, - "pucch_ConfigDedicated is null for TDD!\n"); - if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&& - (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) { - harq_information->harq_information_rel10_tdd.ack_nack_mode = 1; // multiplexing - } - else { - harq_information->harq_information_rel10_tdd.ack_nack_mode = 0; // bundling - } - harq_information->harq_information_rel10_tdd.harq_size = 2; - harq_information->harq_information_rel10_tdd.n_pucch_1_0 = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP; - harq_information->harq_information_rel10_tdd.number_of_pucch_resources = 1; - } - else { - harq_information->harq_information_rel9_fdd.number_of_pucch_resources = 1; - harq_information->harq_information_rel9_fdd.ack_nack_mode = 0; // 1a/b - harq_information->harq_information_rel9_fdd.harq_size = 2; - harq_information->harq_information_rel9_fdd.n_pucch_1_0 = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP; +void +fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t * + ul_config_pdu, uint8_t cqi_req, + COMMON_channels_t * cc, + struct PhysicalConfigDedicated + *physicalConfigDedicated, + uint8_t tmode, uint32_t handle, + uint16_t rnti, + uint8_t resource_block_start, + uint8_t + number_of_resource_blocks, + uint8_t mcs, + uint8_t cyclic_shift_2_for_drms, + uint8_t + frequency_hopping_enabled_flag, + uint8_t frequency_hopping_bits, + uint8_t new_data_indication, + uint8_t redundancy_version, + uint8_t harq_process_number, + uint8_t ul_tx_mode, + uint8_t current_tx_nb, + uint8_t n_srs, uint16_t size) +{ + memset((void *) ul_config_pdu, 0, + sizeof(nfapi_ul_config_request_pdu_t)); + + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_pdu)); + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = handle; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = rnti; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = + resource_block_start; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = + number_of_resource_blocks; + if (mcs < 11) + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; + else if (mcs < 21) + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 4; + else + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 6; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = + cyclic_shift_2_for_drms; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8. + frequency_hopping_enabled_flag = frequency_hopping_enabled_flag; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = + frequency_hopping_bits; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = + new_data_indication; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = + redundancy_version; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = + harq_process_number; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = ul_tx_mode; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = current_tx_nb; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = n_srs; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = size; + + if (cqi_req == 1) { + // Add CQI portion + ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE; + ul_config_pdu->pdu_size = + (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_cqi_ri_pdu)); + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9.report_type = 1; + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.number_of_cc = 1; + LOG_D(MAC, "report_type %d\n", + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9.report_type); + + if (cc->p_eNB <= 2 + && (tmode == 3 || tmode == 4 || tmode == 8 || tmode == 9 + || tmode == 10)) + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 1; + else if (cc->p_eNB <= 2) + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 0; + else if (cc->p_eNB == 4) + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 2; + + AssertFatal(physicalConfigDedicated->cqi_ReportConfig != NULL, + "physicalConfigDedicated->cqi_ReportConfig is null!\n"); + AssertFatal(physicalConfigDedicated-> + cqi_ReportConfig->cqi_ReportModeAperiodic != NULL, + "physicalConfigDedicated->cqi_ReportModeAperiodic is null!\n"); + AssertFatal(physicalConfigDedicated->pusch_ConfigDedicated != NULL, + "physicalConfigDedicated->puschConfigDedicated is null!\n"); + + for (int ri = 0; + ri < + (1 << ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.cc[0].ri_size); ri++) + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9. + aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[ri] = + get_dl_cqi_pmi_size_pusch(cc, tmode, 1 + ri, + physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic); + + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9.delta_offset_cqi = + physicalConfigDedicated->pusch_ConfigDedicated-> + betaOffset_CQI_Index; + ul_config_pdu->ulsch_cqi_ri_pdu. + cqi_ri_information.cqi_ri_information_rel9.delta_offset_ri = + physicalConfigDedicated->pusch_ConfigDedicated-> + betaOffset_RI_Index; } - break; - } // get Tmode -} - -uint16_t fill_nfapi_uci_acknak(module_id_t module_idP, - int CC_idP, - uint16_t rntiP, - uint16_t absSFP, - uint8_t cce_idxP) -{ - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - - int ackNAK_absSF = get_pucch1_absSF(cc,absSFP); - nfapi_ul_config_request_body_t *ul_req = &eNB->UL_req_tmp[CC_idP][ackNAK_absSF%10].ul_config_request_body; - nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; - - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_uci_harq_pdu)); - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0; // don't know how to use this - ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti = rntiP; - - fill_nfapi_harq_information(module_idP,CC_idP, - rntiP, - absSFP, - &ul_config_pdu->uci_harq_pdu.harq_information, - cce_idxP); - LOG_D(MAC,"Filled in UCI HARQ request for rnti %x SF %d.%d acknakSF %d.%d, cce_idxP %d-> n1_pucch %d\n",rntiP, - absSFP/10,absSFP%10,ackNAK_absSF/10,ackNAK_absSF%10,cce_idxP,ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel9_fdd.n_pucch_1_0); - - ul_req->number_of_pdus++; - - return(((ackNAK_absSF/10)<<4) + (ackNAK_absSF%10)); -} - -void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, - nfapi_dl_config_request_body_t *dl_req, - uint16_t length, - uint16_t pdu_index, - uint16_t rnti, - uint8_t resource_allocation_type, - uint8_t virtual_resource_block_assignment_flag, - uint16_t resource_block_coding, - uint8_t modulation, - uint8_t redundancy_version, - uint8_t transport_blocks, - uint8_t transport_block_to_codeword_swap_flag, - uint8_t transmission_scheme, - uint8_t number_of_layers, - uint8_t number_of_subbands, - // uint8_t codebook_index, - uint8_t ue_category_capacity, - uint8_t pa, - uint8_t delta_power_offset_index, - uint8_t ngap, - uint8_t nprb, - uint8_t transmission_mode, - uint8_t num_bf_prb_per_subband, - uint8_t num_bf_vector - ) -{ - nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = length; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = pdu_index; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = resource_allocation_type; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = virtual_resource_block_assignment_flag; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = resource_block_coding; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = modulation; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = redundancy_version; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = transport_blocks; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = transport_block_to_codeword_swap_flag; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = transmission_scheme; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = number_of_layers; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = number_of_subbands; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = codebook_index; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = ue_category_capacity; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = pa; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = delta_power_offset_index; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = ngap; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = nprb; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = transmission_mode; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = num_bf_prb_per_subband; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = num_bf_vector; - dl_req->number_pdu++; -} - -uint16_t fill_nfapi_tx_req(nfapi_tx_request_body_t *tx_req_body,uint16_t absSF,uint16_t pdu_length, uint16_t pdu_index, uint8_t *pdu) -{ - nfapi_tx_request_pdu_t *TX_req = &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus]; - LOG_D(MAC,"Filling TX_req %d for pdu length %d\n",tx_req_body->number_of_pdus,pdu_length); - TX_req->pdu_length = pdu_length; - TX_req->pdu_index = pdu_index; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = pdu_length; - TX_req->segments[0].segment_data = pdu; - tx_req_body->number_of_pdus++; - - return(((absSF/10)<<4) + (absSF%10)); -} - -void fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t *ul_config_pdu, - uint8_t cqi_req, - COMMON_channels_t *cc, - struct PhysicalConfigDedicated *physicalConfigDedicated, - uint8_t tmode, - uint32_t handle, - uint16_t rnti, - uint8_t resource_block_start, - uint8_t number_of_resource_blocks, - uint8_t mcs, - uint8_t cyclic_shift_2_for_drms, - uint8_t frequency_hopping_enabled_flag, - uint8_t frequency_hopping_bits, - uint8_t new_data_indication, - uint8_t redundancy_version, - uint8_t harq_process_number, - uint8_t ul_tx_mode, - uint8_t current_tx_nb, - uint8_t n_srs, - uint16_t size - ) -{ - memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t)); - - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_pdu)); - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle = handle; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti = rnti; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start = resource_block_start; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = number_of_resource_blocks; - if (mcs<11) ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2; - else if (mcs<21) ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 4; - else ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 6; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = cyclic_shift_2_for_drms; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag = frequency_hopping_enabled_flag; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = frequency_hopping_bits; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication = new_data_indication; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version = redundancy_version; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number = harq_process_number; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = ul_tx_mode; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = current_tx_nb; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs = n_srs; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = size; - - if (cqi_req == 1) { - // Add CQI portion - ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE; - ul_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_cqi_ri_pdu)); - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type = 1; - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.number_of_cc = 1; - LOG_D(MAC,"report_type %d\n",ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type); - - if (cc->p_eNB<=2 && (tmode==3||tmode==4||tmode==8||tmode==9||tmode==10)) - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 1; - else if (cc->p_eNB<=2) - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 0; - else if (cc->p_eNB==4) - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 2; - - AssertFatal(physicalConfigDedicated->cqi_ReportConfig!=NULL,"physicalConfigDedicated->cqi_ReportConfig is null!\n"); - AssertFatal(physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic!=NULL,"physicalConfigDedicated->cqi_ReportModeAperiodic is null!\n"); - AssertFatal(physicalConfigDedicated->pusch_ConfigDedicated!=NULL,"physicalConfigDedicated->puschConfigDedicated is null!\n"); - - for (int ri=0; - ri<(1<<ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size); - ri++) - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[ri] = - get_dl_cqi_pmi_size_pusch(cc, - tmode, - 1+ri, - physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic); - - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.delta_offset_cqi = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index; - ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.delta_offset_ri = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index; - } } #ifdef Rel14 -void fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t *ul_config_pdu, - uint8_t ue_type, - uint16_t total_number_of_repetitions, - uint16_t repetition_number, - uint16_t initial_transmission_sf_io) +void +fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t * + ul_config_pdu, uint8_t ue_type, + uint16_t + total_number_of_repetitions, + uint16_t repetition_number, + uint16_t initial_transmission_sf_io) { - // Re13 fields - - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type = ue_type; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions = total_number_of_repetitions; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number = repetition_number; - ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io = initial_transmission_sf_io; + // Re13 fields + + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type = ue_type; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions = + total_number_of_repetitions; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number = + repetition_number; + ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io = + initial_transmission_sf_io; } int get_numnarrowbands(long dl_Bandwidth) { - int nb_tab[6] = {1,2,4,8,12,16}; + int nb_tab[6] = { 1, 2, 4, 8, 12, 16 }; - AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n"); - return(nb_tab[dl_Bandwidth]); + AssertFatal(dl_Bandwidth < 7 + || dl_Bandwidth >= 0, "dl_Bandwidth not in [0..6]\n"); + return (nb_tab[dl_Bandwidth]); } int get_numnarrowbandbits(long dl_Bandwidth) { - int nbbits_tab[6] = {0,1,2,3,4,4}; + int nbbits_tab[6] = { 0, 1, 2, 3, 4, 4 }; - AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n"); - return(nbbits_tab[dl_Bandwidth]); + AssertFatal(dl_Bandwidth < 7 + || dl_Bandwidth >= 0, "dl_Bandwidth not in [0..6]\n"); + return (nbbits_tab[dl_Bandwidth]); } //This implements the frame/subframe condition for first subframe of MPDCCH transmission (Section 9.1.5 36.213, Rel 13/14) -int startSF_fdd_RA_times2[8] = {2,3,4,5,8,10,16,20}; -int startSF_tdd_RA[7] = {1,2,4,5,8,10,20}; +int startSF_fdd_RA_times2[8] = { 2, 3, 4, 5, 8, 10, 16, 20 }; +int startSF_tdd_RA[7] = { 1, 2, 4, 5, 8, 10, 20 }; -int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type,int UE_id) +int +mpdcch_sf_condition(eNB_MAC_INST * eNB, int CC_id, frame_t frameP, + sub_frame_t subframeP, int rmax, + MPDCCH_TYPES_t mpdcch_type, int UE_id) { - struct PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; - - int T; - EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11; - - switch (mpdcch_type) { - case TYPE0: - AssertFatal(1==0,"MPDCCH Type 0 not handled yet\n"); - break; - case TYPE1: - AssertFatal(1==0,"MPDCCH Type 1 not handled yet\n"); - break; - case TYPE1A: - AssertFatal(1==0,"MPDCCH Type 1A not handled yet\n"); - break; - case TYPE2: // RAR - AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13!=NULL, - "mpdcch_startSF_CSS_RA_r13 is null\n"); - AssertFatal(rmax>0,"rmax is 0!\b"); - if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD - T = rmax*startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]>>1; - else //TDD - T = rmax*startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13]; - break; - case TYPE2A: - AssertFatal(1==0,"MPDCCH Type 2A not handled yet\n"); - break; - case TYPEUESPEC: - epdcch_setconfig_r11= eNB->UE_list.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0] ; - - AssertFatal(epdcch_setconfig_r11 != NULL," epdcch_setconfig_r11 is null for UE specific \n"); - AssertFatal(epdcch_setconfig_r11->ext2 != NULL," ext2 doesn't exist in epdcch config ' \n"); - - if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD - T = rmax*startSF_fdd_RA_times2[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.fdd_r13]>>1; - else //TDD - T = rmax*startSF_tdd_RA[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.tdd_r13]; - - break; - default: - return(0); - } + struct PRACH_ConfigSIB_v1310 *ext4_prach = + eNB->common_channels[CC_id].radioResourceConfigCommon_BR-> + ext4->prach_ConfigCommon_v1310; + + int T; + EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11; + + switch (mpdcch_type) { + case TYPE0: + AssertFatal(1 == 0, "MPDCCH Type 0 not handled yet\n"); + break; + case TYPE1: + AssertFatal(1 == 0, "MPDCCH Type 1 not handled yet\n"); + break; + case TYPE1A: + AssertFatal(1 == 0, "MPDCCH Type 1A not handled yet\n"); + break; + case TYPE2: // RAR + AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13 != NULL, + "mpdcch_startSF_CSS_RA_r13 is null\n"); + AssertFatal(rmax > 0, "rmax is 0!\b"); + if (eNB->common_channels[CC_id].tdd_Config == NULL) //FDD + T = rmax * + startSF_fdd_RA_times2[ext4_prach-> + mpdcch_startSF_CSS_RA_r13-> + choice.fdd_r13] >> 1; + else //TDD + T = rmax * + startSF_tdd_RA[ext4_prach-> + mpdcch_startSF_CSS_RA_r13->choice.tdd_r13]; + break; + case TYPE2A: + AssertFatal(1 == 0, "MPDCCH Type 2A not handled yet\n"); + break; + case TYPEUESPEC: + epdcch_setconfig_r11 = + eNB->UE_list.UE_template[CC_id][UE_id]. + physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11. + choice.setup.setConfigToAddModList_r11->list.array[0]; + + AssertFatal(epdcch_setconfig_r11 != NULL, + " epdcch_setconfig_r11 is null for UE specific \n"); + AssertFatal(epdcch_setconfig_r11->ext2 != NULL, + " ext2 doesn't exist in epdcch config ' \n"); + + if (eNB->common_channels[CC_id].tdd_Config == NULL) //FDD + T = rmax * + startSF_fdd_RA_times2[epdcch_setconfig_r11-> + ext2->mpdcch_config_r13->choice. + setup.mpdcch_StartSF_UESS_r13.choice. + fdd_r13] >> 1; + else //TDD + T = rmax * + startSF_tdd_RA[epdcch_setconfig_r11-> + ext2->mpdcch_config_r13->choice. + setup.mpdcch_StartSF_UESS_r13.choice. + tdd_r13]; + + break; + default: + return (0); + } - AssertFatal(T>0,"T is 0!\n"); - if (((10*frameP) + subframeP)%T == 0) return(1); - else return(0); + AssertFatal(T > 0, "T is 0!\n"); + if (((10 * frameP) + subframeP) % T == 0) + return (1); + else + return (0); } -int narrowband_to_first_rb(COMMON_channels_t *cc, int nb_index) +int narrowband_to_first_rb(COMMON_channels_t * cc, int nb_index) { - switch (cc->mib->message.dl_Bandwidth) { - case 0: // 6 PRBs, N_NB=1, i_0=0 - return(0); - break; - case 3: // 50 PRBs, N_NB=8, i_0=1 - return((int)(1+(6*nb_index))); - break; - case 5: // 100 PRBs, N_NB=16, i_0=2 - return((int)(2+(6*nb_index))); - break; - case 1: // 15 PRBs N_NB=2, i_0=1 - if (nb_index>0) return(1); - else return(0); - break; - case 2: // 25 PRBs, N_NB=4, i_0=0 - if (nb_index>1) return(1+(6*nb_index)); - else return((6*nb_index)); - break; - case 4: // 75 PRBs, N_NB=12, i_0=1 - if (nb_index>5) return(2+(6*nb_index)); - else return(1+(6*nb_index)); - break; - default: - AssertFatal(1==0,"Impossible dl_Bandwidth %d\n",(int)cc->mib->message.dl_Bandwidth); - break; - } + switch (cc->mib->message.dl_Bandwidth) { + case 0: // 6 PRBs, N_NB=1, i_0=0 + return (0); + break; + case 3: // 50 PRBs, N_NB=8, i_0=1 + return ((int) (1 + (6 * nb_index))); + break; + case 5: // 100 PRBs, N_NB=16, i_0=2 + return ((int) (2 + (6 * nb_index))); + break; + case 1: // 15 PRBs N_NB=2, i_0=1 + if (nb_index > 0) + return (1); + else + return (0); + break; + case 2: // 25 PRBs, N_NB=4, i_0=0 + if (nb_index > 1) + return (1 + (6 * nb_index)); + else + return ((6 * nb_index)); + break; + case 4: // 75 PRBs, N_NB=12, i_0=1 + if (nb_index > 5) + return (2 + (6 * nb_index)); + else + return (1 + (6 * nb_index)); + break; + default: + AssertFatal(1 == 0, "Impossible dl_Bandwidth %d\n", + (int) cc->mib->message.dl_Bandwidth); + break; + } } #endif @@ -1511,23 +1843,23 @@ int narrowband_to_first_rb(COMMON_channels_t *cc, int nb_index) void init_ue_sched_info(void) //------------------------------------------------------------------------------ { - module_id_t i,j,k; - - for (i=0; i<NUMBER_OF_eNB_MAX; i++) { - for (k=0; k<MAX_NUM_CCs; k++) { - for (j=0; j<NUMBER_OF_UE_MAX; j++) { - // init DL - eNB_dlsch_info[i][k][j].weight = 0; - eNB_dlsch_info[i][k][j].subframe = 0; - eNB_dlsch_info[i][k][j].serving_num = 0; - eNB_dlsch_info[i][k][j].status = S_DL_NONE; - // init UL - eNB_ulsch_info[i][k][j].subframe = 0; - eNB_ulsch_info[i][k][j].serving_num = 0; - eNB_ulsch_info[i][k][j].status = S_UL_NONE; - } + module_id_t i, j, k; + + for (i = 0; i < NUMBER_OF_eNB_MAX; i++) { + for (k = 0; k < MAX_NUM_CCs; k++) { + for (j = 0; j < NUMBER_OF_UE_MAX; j++) { + // init DL + eNB_dlsch_info[i][k][j].weight = 0; + eNB_dlsch_info[i][k][j].subframe = 0; + eNB_dlsch_info[i][k][j].serving_num = 0; + eNB_dlsch_info[i][k][j].status = S_DL_NONE; + // init UL + eNB_ulsch_info[i][k][j].subframe = 0; + eNB_ulsch_info[i][k][j].serving_num = 0; + eNB_ulsch_info[i][k][j].status = S_UL_NONE; + } + } } - } } @@ -1536,82 +1868,85 @@ void init_ue_sched_info(void) unsigned char get_ue_weight(module_id_t module_idP, int CC_idP, int ue_idP) //------------------------------------------------------------------------------ { - return(eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight); + return (eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight); } //------------------------------------------------------------------------------ int find_UE_id(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - int UE_id; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) { - return(UE_id); + int UE_id; + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; + if (UE_list->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == + rntiP) { + return (UE_id); + } } - } - return(-1); + return (-1); } //------------------------------------------------------------------------------ int find_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - int RA_id; - AssertFatal(RC.mac[mod_idP],"RC.mac[%d] is null\n",mod_idP); + int RA_id; + AssertFatal(RC.mac[mod_idP], "RC.mac[%d] is null\n", mod_idP); - RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[CC_idP].RA_template[0]; + RA_t *ra = (RA_t *) & RC.mac[mod_idP]->common_channels[CC_idP].ra[0]; - for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) { - LOG_D(MAC,"Checking RA_id %d for %x : RA_active %d, wait_ack_Msg4 %d\n", - RA_id,rntiP, - RA_template[RA_id].RA_active, - RA_template[RA_id].wait_ack_Msg4); + for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) { + LOG_D(MAC, + "Checking RA_id %d for %x : state %d\n", + RA_id, rntiP, ra[RA_id].state); - if (RA_template[RA_id].RA_active==TRUE && - RA_template[RA_id].wait_ack_Msg4 == 0 && - RA_template[RA_id].rnti == rntiP) return(RA_id); - } - return(-1); + if (ra[RA_id].state != IDLE && + ra[RA_id].rnti == rntiP) + return (RA_id); + } + return (-1); } //------------------------------------------------------------------------------ -int UE_num_active_CC(UE_list_t *listP,int ue_idP) +int UE_num_active_CC(UE_list_t * listP, int ue_idP) //------------------------------------------------------------------------------ { - return(listP->numactiveCCs[ue_idP]); + return (listP->numactiveCCs[ue_idP]); } //------------------------------------------------------------------------------ -int UE_PCCID(module_id_t mod_idP,int ue_idP) +int UE_PCCID(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return(RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]); + return (RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]); } //------------------------------------------------------------------------------ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP,ue_idP)][ue_idP].rnti; + rnti_t rnti = + RC.mac[mod_idP]-> + UE_list.UE_template[UE_PCCID(mod_idP, ue_idP)][ue_idP].rnti; - if (rnti>0) { - return (rnti); - } + if (rnti > 0) { + return (rnti); + } - LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP); - //display_backtrace(); - return(NOT_A_RNTI); + LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP); + //display_backtrace(); + return (NOT_A_RNTI); } //------------------------------------------------------------------------------ boolean_t is_UE_active(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return(RC.mac[mod_idP]->UE_list.active[ue_idP]); + return (RC.mac[mod_idP]->UE_list.active[ue_idP]); } /* @@ -1639,320 +1974,336 @@ uint8_t find_active_UEs(module_id_t module_idP,int CC_id){ // get aggregation (L) form phy for a give UE -unsigned char get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt) +unsigned char +get_aggregation(uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt) { - unsigned char aggregation=3; + unsigned char aggregation = 3; + + switch (dci_fmt) { + case format0: + aggregation = cqi2fmt0_agg[bw_index][cqi]; + break; + case format1: + case format1A: + case format1B: + case format1D: + aggregation = cqi2fmt1x_agg[bw_index][cqi]; + break; + case format2: + case format2A: + case format2B: + case format2C: + case format2D: + aggregation = cqi2fmt2x_agg[bw_index][cqi]; + break; + case format1C: + case format1E_2A_M10PRB: + case format3: + case format3A: + case format4: + default: + LOG_W(MAC, "unsupported DCI format %d\n", dci_fmt); + } - switch (dci_fmt){ - case format0: - aggregation = cqi2fmt0_agg[bw_index][cqi]; - break; - case format1: - case format1A: - case format1B: - case format1D: - aggregation = cqi2fmt1x_agg[bw_index][cqi]; - break; - case format2: - case format2A: - case format2B: - case format2C: - case format2D: - aggregation = cqi2fmt2x_agg[bw_index][cqi]; - break; - case format1C: - case format1E_2A_M10PRB: - case format3: - case format3A: - case format4: - default: - LOG_W(MAC,"unsupported DCI format %d\n",dci_fmt); - } - - LOG_D(MAC,"Aggregation level %d (cqi %d, bw_index %d, format %d)\n", - 1<<aggregation, cqi,bw_index,dci_fmt); + LOG_D(MAC, "Aggregation level %d (cqi %d, bw_index %d, format %d)\n", + 1 << aggregation, cqi, bw_index, dci_fmt); - return 1<<aggregation; + return 1 << aggregation; } -void dump_ue_list(UE_list_t *listP, int ul_flag) +void dump_ue_list(UE_list_t * listP, int ul_flag) { - int j; + int j; - if ( ul_flag == 0 ) { - for (j=listP->head; j>=0; j=listP->next[j]) { - LOG_T(MAC,"node %d => %d\n",j,listP->next[j]); - } - } else { - for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) { - LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]); + if (ul_flag == 0) { + for (j = listP->head; j >= 0; j = listP->next[j]) { + LOG_T(MAC, "node %d => %d\n", j, listP->next[j]); + } + } else { + for (j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { + LOG_T(MAC, "node %d => %d\n", j, listP->next_ul[j]); + } } - } } -int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP - #ifdef Rel14 - ,uint8_t rach_resource_type - #endif - ) -{ - int UE_id; - int i, j; - - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - - LOG_D(MAC,"[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",mod_idP,cc_idP,rntiP,UE_list->avail,UE_list->num_UEs); - dump_ue_list(UE_list,0); - - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] == TRUE) continue; - UE_id = i; - memset(&UE_list->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); - UE_list->UE_template[cc_idP][UE_id].rnti = rntiP; - UE_list->UE_template[cc_idP][UE_id].configured = FALSE; - UE_list->numactiveCCs[UE_id] = 1; - UE_list->numactiveULCCs[UE_id] = 1; - UE_list->pCC_id[UE_id] = cc_idP; - UE_list->ordered_CCids[0][UE_id] = cc_idP; - UE_list->ordered_ULCCids[0][UE_id] = cc_idP; - UE_list->num_UEs++; - UE_list->active[UE_id] = TRUE; +int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP, int harq_pidP +#ifdef Rel14 + , uint8_t rach_resource_type +#endif + ) +{ + int UE_id; + int i, j; + + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + + LOG_D(MAC, + "[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n", + mod_idP, cc_idP, rntiP, UE_list->avail, UE_list->num_UEs); + dump_ue_list(UE_list, 0); + + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] == TRUE) + continue; + UE_id = i; + memset(&UE_list->UE_template[cc_idP][UE_id], 0, + sizeof(UE_TEMPLATE)); + UE_list->UE_template[cc_idP][UE_id].rnti = rntiP; + UE_list->UE_template[cc_idP][UE_id].configured = FALSE; + UE_list->numactiveCCs[UE_id] = 1; + UE_list->numactiveULCCs[UE_id] = 1; + UE_list->pCC_id[UE_id] = cc_idP; + UE_list->ordered_CCids[0][UE_id] = cc_idP; + UE_list->ordered_ULCCids[0][UE_id] = cc_idP; + UE_list->num_UEs++; + UE_list->active[UE_id] = TRUE; #if defined(USRP_REC_PLAY) // not specific to record/playback ? - UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; + UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; #endif #ifdef Rel14 - UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type ; + UE_list->UE_template[cc_idP][UE_id].rach_resource_type = + rach_resource_type; #endif - memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl)); - memset((void*)&UE_list->eNB_UE_stats[cc_idP][UE_id],0,sizeof(eNB_UE_STATS)); - - UE_list->UE_sched_ctrl[UE_id].ta_update = 31; - - for (j=0; j<8; j++) { - UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = (j==0)?1:0; // 1 because first transmission is with format1A (Msg4) for harq_pid 0 - UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j==harq_pidP)?0:1; // 1st transmission is with Msg3; - UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; - UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; + memset((void *) &UE_list->UE_sched_ctrl[UE_id], 0, + sizeof(UE_sched_ctrl)); + memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], 0, + sizeof(eNB_UE_STATS)); + + UE_list->UE_sched_ctrl[UE_id].ta_update = 31; + + for (j = 0; j < 8; j++) { + UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = (j == 0) ? 1 : 0; // 1 because first transmission is with format1A (Msg4) for harq_pid 0 + UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j == harq_pidP) ? 0 : 1; // 1st transmission is with Msg3; + UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; + UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; + } + + eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING; + eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING; + LOG_D(MAC, "[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n", + mod_idP, UE_id, cc_idP, rntiP); + dump_ue_list(UE_list, 0); + return (UE_id); } - eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING; - eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING; - LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP); - dump_ue_list(UE_list,0); - return(UE_id); - } - - printf("MAC: cannot add new UE for rnti %x\n", rntiP); - LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n"); - dump_ue_list(UE_list,0); - return(-1); + printf("MAC: cannot add new UE for rnti %x\n", rntiP); + LOG_E(MAC, + "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n"); + dump_ue_list(UE_list, 0); + return (-1); } //------------------------------------------------------------------------------ -int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) +int rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - int i; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - int UE_id = find_UE_id(mod_idP,rntiP); - int pCC_id; - - if (UE_id == -1) { - LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP); - return 0; - } - - pCC_id = UE_PCCID(mod_idP,UE_id); - - LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP); - dump_ue_list(UE_list,0); - - UE_list->active[UE_id] = FALSE; - UE_list->num_UEs--; - - if (UE_list->head == UE_id) UE_list->head=UE_list->next[UE_id]; - else UE_list->next[prev(UE_list,UE_id,0)]=UE_list->next[UE_id]; - if (UE_list->head_ul == UE_id) UE_list->head_ul=UE_list->next_ul[UE_id]; - else UE_list->next_ul[prev(UE_list,UE_id,0)]=UE_list->next_ul[UE_id]; - - // clear all remaining pending transmissions - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3] = 0; - - UE_list->UE_template[pCC_id][UE_id].ul_SR = 0; - UE_list->UE_template[pCC_id][UE_id].rnti = NOT_A_RNTI; - UE_list->UE_template[pCC_id][UE_id].ul_active = FALSE; - eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; - eNB_ulsch_info[mod_idP][pCC_id][UE_id].status = S_UL_NONE; - eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; - eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE; - - // check if this has an RA process active - RA_TEMPLATE *RA_template; - for (i=0;i<NB_RA_PROC_MAX;i++) { - RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[pCC_id].RA_template[i]; - if (RA_template->rnti == rntiP){ - RA_template->RA_active=FALSE; - RA_template->generate_rar=0; - RA_template->generate_Msg4=0; - RA_template->wait_ack_Msg4=0; - RA_template->timing_offset=0; - RA_template->RRC_timer=20; - RA_template->rnti = 0; - //break; + int i; + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + int UE_id = find_UE_id(mod_idP, rntiP); + int pCC_id; + + if (UE_id == -1) { + LOG_W(MAC, "rrc_mac_remove_ue: UE %x not found\n", rntiP); + return 0; } - } - return 0; -} + pCC_id = UE_PCCID(mod_idP, UE_id); -int prev(UE_list_t *listP, int nodeP, int ul_flag) -{ - int j; - - if (ul_flag == 0 ) { - if (nodeP==listP->head) { - return(nodeP); - } + LOG_I(MAC, "Removing UE %d from Primary CC_id %d (rnti %x)\n", UE_id, + pCC_id, rntiP); + dump_ue_list(UE_list, 0); - for (j=listP->head; j>=0; j=listP->next[j]) { - if (listP->next[j]==nodeP) { - return(j); - } - } - } else { - if (nodeP==listP->head_ul) { - return(nodeP); - } + UE_list->active[UE_id] = FALSE; + UE_list->num_UEs--; - for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) { - if (listP->next_ul[j]==nodeP) { - return(j); - } + if (UE_list->head == UE_id) + UE_list->head = UE_list->next[UE_id]; + else + UE_list->next[prev(UE_list, UE_id, 0)] = UE_list->next[UE_id]; + if (UE_list->head_ul == UE_id) + UE_list->head_ul = UE_list->next_ul[UE_id]; + else + UE_list->next_ul[prev(UE_list, UE_id, 0)] = + UE_list->next_ul[UE_id]; + + // clear all remaining pending transmissions + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3] = 0; + + UE_list->UE_template[pCC_id][UE_id].ul_SR = 0; + UE_list->UE_template[pCC_id][UE_id].rnti = NOT_A_RNTI; + UE_list->UE_template[pCC_id][UE_id].ul_active = FALSE; + eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; + eNB_ulsch_info[mod_idP][pCC_id][UE_id].status = S_UL_NONE; + eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; + eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE; + + // check if this has an RA process active + RA_t *ra; + for (i = 0; i < NB_RA_PROC_MAX; i++) { + ra = (RA_t *) & RC.mac[mod_idP]->common_channels[pCC_id].ra[i]; + if (ra->rnti == rntiP) { + ra->state = IDLE; + ra->timing_offset = 0; + ra->RRC_timer = 20; + ra->rnti = 0; + //break; + } } - } - - LOG_E(MAC,"error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n", - nodeP, (ul_flag == 0)? "DL" : "UL"); - dump_ue_list(listP, ul_flag); - return(-1); + return 0; } -void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag) +int prev(UE_list_t * listP, int nodeP, int ul_flag) { - int prev_i,prev_j,next_i,next_j; - - LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP); - dump_ue_list(listP,ul_flag); - - prev_i = prev(listP,nodeiP,ul_flag); - prev_j = prev(listP,nodejP,ul_flag); + int j; + + if (ul_flag == 0) { + if (nodeP == listP->head) { + return (nodeP); + } + + for (j = listP->head; j >= 0; j = listP->next[j]) { + if (listP->next[j] == nodeP) { + return (j); + } + } + } else { + if (nodeP == listP->head_ul) { + return (nodeP); + } + + for (j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { + if (listP->next_ul[j] == nodeP) { + return (j); + } + } + } - AssertFatal((prev_i>=0) && (prev_j>=0), - "swap_UEs: problem"); + LOG_E(MAC, + "error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n", + nodeP, (ul_flag == 0) ? "DL" : "UL"); + dump_ue_list(listP, ul_flag); - if (ul_flag == 0) { - next_i = listP->next[nodeiP]; - next_j = listP->next[nodejP]; - } else { - next_i = listP->next_ul[nodeiP]; - next_j = listP->next_ul[nodejP]; - } + return (-1); +} - LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n", - (ul_flag == 0)? "DL" : "UL", - next_i,next_j,listP->head); +void swap_UEs(UE_list_t * listP, int nodeiP, int nodejP, int ul_flag) +{ + int prev_i, prev_j, next_i, next_j; - if (ul_flag == 0 ) { + LOG_T(MAC, "Swapping UE %d,%d\n", nodeiP, nodejP); + dump_ue_list(listP, ul_flag); - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC,"Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); + prev_i = prev(listP, nodeiP, ul_flag); + prev_j = prev(listP, nodejP, ul_flag); - listP->next[nodeiP] = next_j; - listP->next[nodejP] = nodeiP; + AssertFatal((prev_i >= 0) && (prev_j >= 0), "swap_UEs: problem"); - if (nodeiP==listP->head) { // case i j n(j) - listP->head = nodejP; - } else { - listP->next[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC,"Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next[nodejP] = next_i; - listP->next[nodeiP] = nodejP; - - if (nodejP==listP->head) { // case j i n(i) - listP->head = nodeiP; - } else { - listP->next[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - listP->next[nodejP] = next_i; - listP->next[nodeiP] = next_j; - - if (nodeiP==listP->head) { - LOG_T(MAC,"changing head to %d\n",nodejP); - listP->head=nodejP; - listP->next[prev_j] = nodeiP; - } else if (nodejP==listP->head) { - LOG_D(MAC,"changing head to %d\n",nodeiP); - listP->head=nodeiP; - listP->next[prev_i] = nodejP; - } else { - listP->next[prev_i] = nodejP; - listP->next[prev_j] = nodeiP; - } + if (ul_flag == 0) { + next_i = listP->next[nodeiP]; + next_j = listP->next[nodejP]; + } else { + next_i = listP->next_ul[nodeiP]; + next_j = listP->next_ul[nodejP]; } - } else { // ul_flag - - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC,"[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); - listP->next_ul[nodeiP] = next_j; - listP->next_ul[nodejP] = nodeiP; - - if (nodeiP==listP->head_ul) { // case i j n(j) - listP->head_ul = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC,"[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = nodejP; - - if (nodejP==listP->head_ul) { // case j i n(i) - listP->head_ul = nodeiP; - } else { - listP->next_ul[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = next_j; - - if (nodeiP==listP->head_ul) { - LOG_T(MAC,"[UL]changing head to %d\n",nodejP); - listP->head_ul=nodejP; - listP->next_ul[prev_j] = nodeiP; - } else if (nodejP==listP->head_ul) { - LOG_T(MAC,"[UL]changing head to %d\n",nodeiP); - listP->head_ul=nodeiP; - listP->next_ul[prev_i] = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - listP->next_ul[prev_j] = nodeiP; - } + LOG_T(MAC, "[%s] next_i %d, next_i, next_j %d, head %d \n", + (ul_flag == 0) ? "DL" : "UL", next_i, next_j, listP->head); + + if (ul_flag == 0) { + + if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... + LOG_T(MAC, + "Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); + + listP->next[nodeiP] = next_j; + listP->next[nodejP] = nodeiP; + + if (nodeiP == listP->head) { // case i j n(j) + listP->head = nodejP; + } else { + listP->next[prev_i] = nodejP; + } + } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... + LOG_T(MAC, + "Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); + listP->next[nodejP] = next_i; + listP->next[nodeiP] = nodejP; + + if (nodejP == listP->head) { // case j i n(i) + listP->head = nodeiP; + } else { + listP->next[prev_j] = nodeiP; + } + } else { // case ... p(i) i n(i) ... p(j) j n(j) ... + listP->next[nodejP] = next_i; + listP->next[nodeiP] = next_j; + + if (nodeiP == listP->head) { + LOG_T(MAC, "changing head to %d\n", nodejP); + listP->head = nodejP; + listP->next[prev_j] = nodeiP; + } else if (nodejP == listP->head) { + LOG_D(MAC, "changing head to %d\n", nodeiP); + listP->head = nodeiP; + listP->next[prev_i] = nodejP; + } else { + listP->next[prev_i] = nodejP; + listP->next[prev_j] = nodeiP; + } + } + } else { // ul_flag + + if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... + LOG_T(MAC, + "[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); + + listP->next_ul[nodeiP] = next_j; + listP->next_ul[nodejP] = nodeiP; + + if (nodeiP == listP->head_ul) { // case i j n(j) + listP->head_ul = nodejP; + } else { + listP->next_ul[prev_i] = nodejP; + } + } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... + LOG_T(MAC, + "[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); + listP->next_ul[nodejP] = next_i; + listP->next_ul[nodeiP] = nodejP; + + if (nodejP == listP->head_ul) { // case j i n(i) + listP->head_ul = nodeiP; + } else { + listP->next_ul[prev_j] = nodeiP; + } + } else { // case ... p(i) i n(i) ... p(j) j n(j) ... + + listP->next_ul[nodejP] = next_i; + listP->next_ul[nodeiP] = next_j; + + if (nodeiP == listP->head_ul) { + LOG_T(MAC, "[UL]changing head to %d\n", nodejP); + listP->head_ul = nodejP; + listP->next_ul[prev_j] = nodeiP; + } else if (nodejP == listP->head_ul) { + LOG_T(MAC, "[UL]changing head to %d\n", nodeiP); + listP->head_ul = nodeiP; + listP->next_ul[prev_i] = nodejP; + } else { + listP->next_ul[prev_i] = nodejP; + listP->next_ul[prev_j] = nodeiP; + } + } } - } - LOG_T(MAC,"After swap\n"); - dump_ue_list(listP,ul_flag); + LOG_T(MAC, "After swap\n"); + dump_ue_list(listP, ul_flag); } /* @@ -2069,818 +2420,959 @@ void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag) */ // This has to be updated to include BSR information -uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id) +uint8_t +UE_is_to_be_scheduled(module_id_t module_idP, int CC_id, uint8_t UE_id) { - UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id]; - UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; - - // do not schedule UE if UL is not working - if (UE_sched_ctl->ul_failure_timer>0) - return(0); - if (UE_sched_ctl->ul_out_of_sync>0) - return(0); - - LOG_D(MAC,"[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id)); - - if ((UE_template->bsr_info[LCGID0]>0) || - (UE_template->bsr_info[LCGID1]>0) || - (UE_template->bsr_info[LCGID2]>0) || - (UE_template->bsr_info[LCGID3]>0) || - (UE_template->ul_SR>0) || // uplink scheduling request - ((UE_sched_ctl->ul_inactivity_timer>20)&& - (UE_sched_ctl->ul_scheduled==0))|| // every 2 frames when RRC_CONNECTED - ((UE_sched_ctl->ul_inactivity_timer>10)&& - (UE_sched_ctl->ul_scheduled==0)&& - (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) // every Frame when not RRC_CONNECTED - { - LOG_D(MAC,"[eNB %d][PUSCH] UE %d/%x should be scheduled (BSR0 %d,SR %d)\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id), - UE_template->bsr_info[LCGID0], - UE_template->ul_SR); - return(1); - } else { - return(0); - } + UE_TEMPLATE *UE_template = + &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id]; + UE_sched_ctrl *UE_sched_ctl = + &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; + + // do not schedule UE if UL is not working + if (UE_sched_ctl->ul_failure_timer > 0) + return (0); + if (UE_sched_ctl->ul_out_of_sync > 0) + return (0); + + LOG_D(MAC, "[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n", + module_idP, UE_id, UE_RNTI(module_idP, UE_id)); + + if ((UE_template->bsr_info[LCGID0] > 0) || (UE_template->bsr_info[LCGID1] > 0) || (UE_template->bsr_info[LCGID2] > 0) || (UE_template->bsr_info[LCGID3] > 0) || (UE_template->ul_SR > 0) || // uplink scheduling request + ((UE_sched_ctl->ul_inactivity_timer > 20) && (UE_sched_ctl->ul_scheduled == 0)) || // every 2 frames when RRC_CONNECTED + ((UE_sched_ctl->ul_inactivity_timer > 10) && (UE_sched_ctl->ul_scheduled == 0) && (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED))) // every Frame when not RRC_CONNECTED + { + LOG_D(MAC, + "[eNB %d][PUSCH] UE %d/%x should be scheduled (BSR0 %d,SR %d)\n", + module_idP, UE_id, UE_RNTI(module_idP, UE_id), + UE_template->bsr_info[LCGID0], UE_template->ul_SR); + return (1); + } else { + return (0); + } } -uint8_t get_tmode(module_id_t module_idP,int CC_idP,int UE_idP) +uint8_t get_tmode(module_id_t module_idP, int CC_idP, int UE_idP) { - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - struct PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_list.physicalConfigDedicated[CC_idP][UE_idP]; + struct PhysicalConfigDedicated *physicalConfigDedicated = + eNB->UE_list.physicalConfigDedicated[CC_idP][UE_idP]; - if (physicalConfigDedicated == NULL ) { // RRCConnectionSetup not received by UE yet - AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB); - return(cc->p_eNB); - } - else { - AssertFatal(physicalConfigDedicated->antennaInfo!=NULL, - "antennaInfo is null for CCId %d, UEid %d\n",CC_idP,UE_idP); - - AssertFatal(physicalConfigDedicated->antennaInfo->present != PhysicalConfigDedicated__antennaInfo_PR_NOTHING, - "antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n",module_idP,CC_idP); - - if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_explicitValue) { - return(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); - } - else if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_defaultValue) { - AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB); - return(cc->p_eNB); + if (physicalConfigDedicated == NULL) { // RRCConnectionSetup not received by UE yet + AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n", + cc->p_eNB); + return (cc->p_eNB); + } else { + AssertFatal(physicalConfigDedicated->antennaInfo != NULL, + "antennaInfo is null for CCId %d, UEid %d\n", CC_idP, + UE_idP); + + AssertFatal(physicalConfigDedicated->antennaInfo->present != + PhysicalConfigDedicated__antennaInfo_PR_NOTHING, + "antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n", + module_idP, CC_idP); + + if (physicalConfigDedicated->antennaInfo->present == + PhysicalConfigDedicated__antennaInfo_PR_explicitValue) { + return (physicalConfigDedicated->antennaInfo-> + choice.explicitValue.transmissionMode); + } else if (physicalConfigDedicated->antennaInfo->present == + PhysicalConfigDedicated__antennaInfo_PR_defaultValue) { + AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n", + cc->p_eNB); + return (cc->p_eNB); + } else + AssertFatal(1 == 0, "Shouldn't be here\n"); } - else AssertFatal(1==0,"Shouldn't be here\n"); - } } -int8_t get_ULharq(module_id_t module_idP,int CC_idP,uint16_t frameP,uint8_t subframeP) +int8_t +get_ULharq(module_id_t module_idP, int CC_idP, uint16_t frameP, + uint8_t subframeP) { - uint8_t ret = -1; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - - if (cc->tdd_Config==NULL) { // FDD - ret = (((frameP<<1)+subframeP)&7); - } else { - switch (cc->tdd_Config->subframeAssignment) { - case 1: - if ((subframeP==2) || - (subframeP==3) || - (subframeP==7) || - (subframeP==8)) - switch (subframeP) { - case 2: - case 3: - ret = (subframeP-2); - break; - - case 7: - case 8: - ret = (subframeP-5); - break; - - default: - AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment); - break; - } - - break; - - case 2: - AssertFatal((subframeP==2) || (subframeP==7), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment); - ret = (subframeP/7); - break; - - case 3: - AssertFatal((subframeP>1) && (subframeP<5), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment); - ret = (subframeP-2); - break; - - case 4: - AssertFatal((subframeP>1) && (subframeP<4), - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment); - ret = (subframeP-2); - break; + uint8_t ret = -1; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - case 5: - AssertFatal(subframeP==2, - "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment); - ret = (subframeP-2); - break; - - default: - AssertFatal(1==0,"subframe2_harq_pid, Unsupported TDD mode %d\n",(int)cc->tdd_Config->subframeAssignment); - break; + if (cc->tdd_Config == NULL) { // FDD + ret = (((frameP << 1) + subframeP) & 7); + } else { + switch (cc->tdd_Config->subframeAssignment) { + case 1: + if ((subframeP == 2) || + (subframeP == 3) || (subframeP == 7) || (subframeP == 8)) + switch (subframeP) { + case 2: + case 3: + ret = (subframeP - 2); + break; + + case 7: + case 8: + ret = (subframeP - 5); + break; + + default: + AssertFatal(1 == 0, + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframeP, + (int) cc->tdd_Config->subframeAssignment); + break; + } + + break; + + case 2: + AssertFatal((subframeP == 2) || (subframeP == 7), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframeP, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframeP / 7); + break; + + case 3: + AssertFatal((subframeP > 1) && (subframeP < 5), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframeP, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframeP - 2); + break; + + case 4: + AssertFatal((subframeP > 1) && (subframeP < 4), + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframeP, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframeP - 2); + break; + + case 5: + AssertFatal(subframeP == 2, + "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n", + subframeP, + (int) cc->tdd_Config->subframeAssignment); + ret = (subframeP - 2); + break; + + default: + AssertFatal(1 == 0, + "subframe2_harq_pid, Unsupported TDD mode %d\n", + (int) cc->tdd_Config->subframeAssignment); + break; + } } - } - AssertFatal(ret!=-1, - "invalid harq_pid(%d) at SFN/SF = %d/%d\n", (int8_t)ret, frameP, subframeP); - return ret; + AssertFatal(ret != -1, + "invalid harq_pid(%d) at SFN/SF = %d/%d\n", (int8_t) ret, + frameP, subframeP); + return ret; } -uint16_t getRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs) +uint16_t getRIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs) { - uint16_t RIV; + uint16_t RIV; - if (Lcrbs<=(1+(N_RB_DL>>1))) - RIV = (N_RB_DL*(Lcrbs-1)) + RBstart; - else - RIV = (N_RB_DL*(N_RB_DL+1-Lcrbs)) + (N_RB_DL-1-RBstart); + if (Lcrbs <= (1 + (N_RB_DL >> 1))) + RIV = (N_RB_DL * (Lcrbs - 1)) + RBstart; + else + RIV = (N_RB_DL * (N_RB_DL + 1 - Lcrbs)) + (N_RB_DL - 1 - RBstart); - return(RIV); + return (RIV); } -uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, int N_RB_DL, uint32_t *rballoc) +uint32_t +allocate_prbs(int UE_id, unsigned char nb_rb, int N_RB_DL, + uint32_t * rballoc) { - int i; - uint32_t rballoc_dci=0; - unsigned char nb_rb_alloc=0; - - for (i=0; i<(N_RB_DL-2); i+=2) { - if (((*rballoc>>i)&3)==0) { - *rballoc |= (3<<i); - rballoc_dci |= (1<<((12-i)>>1)); - nb_rb_alloc+=2; + int i; + uint32_t rballoc_dci = 0; + unsigned char nb_rb_alloc = 0; + + for (i = 0; i < (N_RB_DL - 2); i += 2) { + if (((*rballoc >> i) & 3) == 0) { + *rballoc |= (3 << i); + rballoc_dci |= (1 << ((12 - i) >> 1)); + nb_rb_alloc += 2; + } + + if (nb_rb_alloc == nb_rb) { + return (rballoc_dci); + } } - if (nb_rb_alloc==nb_rb) { - return(rballoc_dci); - } - } - - if ((N_RB_DL&1)==1) { - if ((*rballoc>>(N_RB_DL-1)&1)==0) { - *rballoc |= (1<<(N_RB_DL-1)); - rballoc_dci |= 1; + if ((N_RB_DL & 1) == 1) { + if ((*rballoc >> (N_RB_DL - 1) & 1) == 0) { + *rballoc |= (1 << (N_RB_DL - 1)); + rballoc_dci |= 1; + } } - } - return(rballoc_dci); + return (rballoc_dci); } int get_bw_index(module_id_t module_id, uint8_t CC_id) { - int bw_index=0; + int bw_index = 0; - int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + int N_RB_DL = + to_prb(RC.mac[module_id]->common_channels[CC_id].mib-> + message.dl_Bandwidth); - switch (N_RB_DL) { - case 6: // 1.4 MHz - bw_index=0; - break; + switch (N_RB_DL) { + case 6: // 1.4 MHz + bw_index = 0; + break; - case 25: // 5HMz - bw_index=1; - break; + case 25: // 5HMz + bw_index = 1; + break; - case 50: // 10HMz - bw_index=2; - break; + case 50: // 10HMz + bw_index = 2; + break; - case 100: // 20HMz - bw_index=3; - break; + case 100: // 20HMz + bw_index = 3; + break; - default: - bw_index=1; - LOG_W(MAC,"[eNB %d] N_RB_DL %d unknown for CC_id %d, setting bw_index to 1\n", module_id, N_RB_DL,CC_id); - break; - } + default: + bw_index = 1; + LOG_W(MAC, + "[eNB %d] N_RB_DL %d unknown for CC_id %d, setting bw_index to 1\n", + module_id, N_RB_DL, CC_id); + break; + } - return bw_index; + return bw_index; } int get_min_rb_unit(module_id_t module_id, uint8_t CC_id) { - int min_rb_unit=0; - int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + int min_rb_unit = 0; + int N_RB_DL = + to_prb(RC.mac[module_id]->common_channels[CC_id].mib-> + message.dl_Bandwidth); - switch (N_RB_DL) { - case 6: // 1.4 MHz - min_rb_unit=1; - break; + switch (N_RB_DL) { + case 6: // 1.4 MHz + min_rb_unit = 1; + break; - case 25: // 5HMz - min_rb_unit=2; - break; + case 25: // 5HMz + min_rb_unit = 2; + break; - case 50: // 10HMz - min_rb_unit=3; - break; + case 50: // 10HMz + min_rb_unit = 3; + break; - case 100: // 20HMz - min_rb_unit=4; - break; + case 100: // 20HMz + min_rb_unit = 4; + break; - default: - min_rb_unit=2; - LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n", - module_id, N_RB_DL, CC_id); - break; - } + default: + min_rb_unit = 2; + LOG_W(MAC, + "[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n", + module_id, N_RB_DL, CC_id); + break; + } - return min_rb_unit; + return min_rb_unit; } -uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t *rballoc) +uint32_t +allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t * rballoc) { - int check=0;//check1=0,check2=0; - uint32_t rballoc_dci=0; - //uint8_t number_of_subbands=13; - - LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n", - rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,N_RBG); - - while((nb_rb >0) && (check < N_RBG)) { - //printf("rballoc[%d] %d\n",check,rballoc[check]); - if(rballoc[check] == 1) { - rballoc_dci |= (1<<((N_RBG-1)-check)); - - switch (N_RB_DL) { - case 6: - nb_rb--; - break; - - case 25: - if ((check == N_RBG-1)) { - nb_rb--; - } else { - nb_rb-=2; - } - - break; - - case 50: - if ((check == N_RBG-1)) { - nb_rb-=2; - } else { - nb_rb-=3; - } - - break; - - case 100: - nb_rb-=4; - break; - } + int check = 0; //check1=0,check2=0; + uint32_t rballoc_dci = 0; + //uint8_t number_of_subbands=13; + + LOG_T(MAC, "*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n", + rballoc[3], rballoc[2], rballoc[1], rballoc[0], nb_rb, N_RBG); + + while ((nb_rb > 0) && (check < N_RBG)) { + //printf("rballoc[%d] %d\n",check,rballoc[check]); + if (rballoc[check] == 1) { + rballoc_dci |= (1 << ((N_RBG - 1) - check)); + + switch (N_RB_DL) { + case 6: + nb_rb--; + break; + + case 25: + if ((check == N_RBG - 1)) { + nb_rb--; + } else { + nb_rb -= 2; + } + + break; + + case 50: + if ((check == N_RBG - 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; } - // printf("rb_alloc %x\n",rballoc_dci); - check = check+1; - // check1 = check1+2; - } - - // rballoc_dci = (rballoc_dci)&(0x1fff); - LOG_T(MAC,"*********RBALLOC : %x\n",rballoc_dci); - // exit(-1); - return (rballoc_dci); + // rballoc_dci = (rballoc_dci)&(0x1fff); + LOG_T(MAC, "*********RBALLOC : %x\n", rballoc_dci); + // exit(-1); + return (rballoc_dci); } int get_subbandsize(uint8_t dl_Bandwidth) { - uint8_t ss[6] = {6,4,4,6,8,8}; + uint8_t ss[6] = { 6, 4, 4, 6, 8, 8 }; - AssertFatal(dl_Bandwidth<6,"dl_Bandwidth %d is out of bounds\n",dl_Bandwidth); + AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth %d is out of bounds\n", + dl_Bandwidth); - return(ss[dl_Bandwidth]); + return (ss[dl_Bandwidth]); } int get_nb_subband(int N_RB_DL) { - int nb_sb=0; + int nb_sb = 0; - switch (N_RB_DL) { - case 6: - nb_sb=0; - break; + switch (N_RB_DL) { + case 6: + nb_sb = 0; + break; - case 15: - nb_sb = 4; // sb_size =4 + case 15: + nb_sb = 4; // sb_size =4 - case 25: - nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs - break; + case 25: + nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs + break; - case 50: // sb_size =6 - nb_sb = 9; - break; + case 50: // sb_size =6 + nb_sb = 9; + break; - case 75: // sb_size =8 - nb_sb = 10; - break; + case 75: // sb_size =8 + nb_sb = 10; + break; - case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs - nb_sb = 13; - break; + case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs + nb_sb = 13; + break; - default: - nb_sb=0; - break; - } + default: + nb_sb = 0; + break; + } - return nb_sb; + return nb_sb; } -void init_CCE_table(int module_idP,int CC_idP) +void init_CCE_table(int module_idP, int CC_idP) { - memset(RC.mac[module_idP]->CCE_table[CC_idP],0,800*sizeof(int)); + memset(RC.mac[module_idP]->CCE_table[CC_idP], 0, 800 * sizeof(int)); } -int get_nCCE_offset(int *CCE_table, - const unsigned char L, - const int nCCE, - const int common_dci, - const unsigned short rnti, - const unsigned char subframe) +int +get_nCCE_offset(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, const unsigned char subframe) { - int search_space_free,m,nb_candidates = 0,l,i; - unsigned int Yk; - /* - printf("CCE Allocation: "); - for (i=0;i<nCCE;i++) - printf("%d.",CCE_table[i]); - printf("\n"); - */ - if (common_dci == 1) { - // check CCE(0 ... L-1) - nb_candidates = (L==4) ? 4 : 2; - nb_candidates = min(nb_candidates,nCCE/L); + int search_space_free, m, nb_candidates = 0, l, i; + unsigned int Yk; + /* + printf("CCE Allocation: "); + for (i=0;i<nCCE;i++) + printf("%d.",CCE_table[i]); + printf("\n"); + */ + if (common_dci == 1) { + // check CCE(0 ... L-1) + nb_candidates = (L == 4) ? 4 : 2; + nb_candidates = min(nb_candidates, nCCE / L); - // printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); + // printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); - for (m = nb_candidates-1 ; m >=0 ; m--) { + for (m = nb_candidates - 1; m >= 0; m--) { - search_space_free = 1; - for (l=0; l<L; l++) { + search_space_free = 1; + for (l = 0; l < L; l++) { - // printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]); - if (CCE_table[(m*L) + l] == 1) { - search_space_free = 0; - break; - } - } + // printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]); + if (CCE_table[(m * L) + l] == 1) { + search_space_free = 0; + break; + } + } - if (search_space_free == 1) { + if (search_space_free == 1) { - // printf("returning %d\n",m*L); + // printf("returning %d\n",m*L); - for (l=0; l<L; l++) - CCE_table[(m*L)+l]=1; - return(m*L); - } - } + for (l = 0; l < L; l++) + CCE_table[(m * L) + l] = 1; + return (m * L); + } + } - return(-1); + return (-1); - } else { // Find first available in ue specific search space - // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) - // compute Yk - Yk = (unsigned int)rnti; + } else { // Find first available in ue specific search space + // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) + // compute Yk + Yk = (unsigned int) rnti; - for (i=0; i<=subframe; i++) - Yk = (Yk*39827)%65537; + for (i = 0; i <= subframe; i++) + Yk = (Yk * 39827) % 65537; - Yk = Yk % (nCCE/L); + Yk = Yk % (nCCE / L); - switch (L) { - case 1: - case 2: - nb_candidates = 6; - break; + switch (L) { + case 1: + case 2: + nb_candidates = 6; + break; - case 4: - case 8: - nb_candidates = 2; - break; + case 4: + case 8: + nb_candidates = 2; + break; - default: - DevParam(L, nCCE, rnti); - break; - } + default: + DevParam(L, nCCE, rnti); + break; + } - LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); + LOG_D(MAC, "rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n", + rnti, Yk, nCCE, nCCE / L, nb_candidates); - for (m = 0 ; m < nb_candidates ; m++) { - search_space_free = 1; + for (m = 0; m < nb_candidates; m++) { + search_space_free = 1; - for (l=0; l<L; l++) { - int cce = (((Yk+m)%(nCCE/L))*L) + l; - if (cce >= nCCE || CCE_table[cce] == 1) { - search_space_free = 0; - break; - } - } + for (l = 0; l < L; l++) { + int cce = (((Yk + m) % (nCCE / L)) * L) + l; + if (cce >= nCCE || CCE_table[cce] == 1) { + search_space_free = 0; + break; + } + } - if (search_space_free == 1) { - for (l=0; l<L; l++) - CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1; + if (search_space_free == 1) { + for (l = 0; l < L; l++) + CCE_table[(((Yk + m) % (nCCE / L)) * L) + l] = 1; - return(((Yk+m)%(nCCE/L))*L); - } - } + return (((Yk + m) % (nCCE / L)) * L); + } + } - return(-1); - } + return (-1); + } } -void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,const int subframe,int L) +void +dump_CCE_table(int *CCE_table, const int nCCE, + const unsigned short rnti, const int subframe, int L) { - int nb_candidates = 0,i; - unsigned int Yk; - - printf("CCE 0: "); - for (i=0;i<nCCE;i++) { - printf("%1d.",CCE_table[i]); - if ((i&7) == 7) - printf("\n CCE %d: ",i); - } + int nb_candidates = 0, i; + unsigned int Yk; + + printf("CCE 0: "); + for (i = 0; i < nCCE; i++) { + printf("%1d.", CCE_table[i]); + if ((i & 7) == 7) + printf("\n CCE %d: ", i); + } - Yk = (unsigned int)rnti; + Yk = (unsigned int) rnti; - for (i=0; i<=subframe; i++) - Yk = (Yk*39827)%65537; + for (i = 0; i <= subframe; i++) + Yk = (Yk * 39827) % 65537; - Yk = Yk % (nCCE/L); + Yk = Yk % (nCCE / L); - switch (L) { - case 1: - case 2: - nb_candidates = 6; - break; + switch (L) { + case 1: + case 2: + nb_candidates = 6; + break; - case 4: - case 8: - nb_candidates = 2; - break; + case 4: + case 8: + nb_candidates = 2; + break; - default: - DevParam(L, nCCE, rnti); - break; - } + default: + DevParam(L, nCCE, rnti); + break; + } - printf("rnti %x, Yk*L = %d, nCCE %d (nCCE/L %d),nb_cand*L %d\n",rnti,Yk*L,nCCE,nCCE/L,nb_candidates*L); + printf("rnti %x, Yk*L = %d, nCCE %d (nCCE/L %d),nb_cand*L %d\n", rnti, + Yk * L, nCCE, nCCE / L, nb_candidates * L); } -uint16_t getnquad(COMMON_channels_t *cc, uint8_t num_pdcch_symbols,uint8_t mi) +uint16_t +getnquad(COMMON_channels_t * cc, uint8_t num_pdcch_symbols, uint8_t mi) { - uint16_t Nreg=0; - - AssertFatal(cc!=NULL,"cc is null\n"); - AssertFatal(cc->mib!=NULL,"cc->mib is null\n"); + uint16_t Nreg = 0; - int N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - int phich_resource = get_phich_resource_times6(cc); + AssertFatal(cc != NULL, "cc is null\n"); + AssertFatal(cc->mib != NULL, "cc->mib is null\n"); - uint8_t Ngroup_PHICH = (phich_resource*N_RB_DL)/48; + int N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + int phich_resource = get_phich_resource_times6(cc); - if (((phich_resource*N_RB_DL)%48) > 0) - Ngroup_PHICH++; + uint8_t Ngroup_PHICH = (phich_resource * N_RB_DL) / 48; - if (cc->Ncp == 1) { - Ngroup_PHICH<<=1; - } + if (((phich_resource * N_RB_DL) % 48) > 0) + Ngroup_PHICH++; - Ngroup_PHICH*=mi; + if (cc->Ncp == 1) { + Ngroup_PHICH <<= 1; + } - if ((num_pdcch_symbols>0) && (num_pdcch_symbols<4)) - switch (N_RB_DL) { - case 6: - Nreg=12+(num_pdcch_symbols-1)*18; - break; + Ngroup_PHICH *= mi; - case 25: - Nreg=50+(num_pdcch_symbols-1)*75; - break; + if ((num_pdcch_symbols > 0) && (num_pdcch_symbols < 4)) + switch (N_RB_DL) { + case 6: + Nreg = 12 + (num_pdcch_symbols - 1) * 18; + break; - case 50: - Nreg=100+(num_pdcch_symbols-1)*150; - break; + case 25: + Nreg = 50 + (num_pdcch_symbols - 1) * 75; + break; - case 100: - Nreg=200+(num_pdcch_symbols-1)*300; - break; + case 50: + Nreg = 100 + (num_pdcch_symbols - 1) * 150; + break; - default: - return(0); - } + case 100: + Nreg = 200 + (num_pdcch_symbols - 1) * 300; + break; - // printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH)); - return(Nreg - 4 - (3*Ngroup_PHICH)); + default: + return (0); + } + // printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH)); + return (Nreg - 4 - (3 * Ngroup_PHICH)); } -uint16_t getnCCE(COMMON_channels_t *cc, uint8_t num_pdcch_symbols, uint8_t mi) +uint16_t +getnCCE(COMMON_channels_t * cc, uint8_t num_pdcch_symbols, uint8_t mi) { - AssertFatal(cc!=NULL,"cc is null\n"); - return(getnquad(cc,num_pdcch_symbols,mi)/9); + AssertFatal(cc != NULL, "cc is null\n"); + return (getnquad(cc, num_pdcch_symbols, mi) / 9); } -uint8_t getmi(COMMON_channels_t *cc,int subframe) +uint8_t getmi(COMMON_channels_t * cc, int subframe) { - AssertFatal(cc!=NULL,"cc is null\n"); + AssertFatal(cc != NULL, "cc is null\n"); - // for FDD - if (cc->tdd_Config==NULL) // FDD - return 1; + // for FDD + if (cc->tdd_Config == NULL) // FDD + return 1; - // for TDD - switch (cc->tdd_Config->subframeAssignment) { - case 0: - if ((subframe==0) || (subframe==5)) - return(2); - else return(1); + // for TDD + switch (cc->tdd_Config->subframeAssignment) { + case 0: + if ((subframe == 0) || (subframe == 5)) + return (2); + else + return (1); - break; + break; - case 1: - if ((subframe==0) || (subframe==5)) - return(0); - else return(1); + case 1: + if ((subframe == 0) || (subframe == 5)) + return (0); + else + return (1); - break; + break; - case 2: - if ((subframe==3) || (subframe==8)) - return(1); - else return(0); + case 2: + if ((subframe == 3) || (subframe == 8)) + return (1); + else + return (0); - break; + break; - case 3: - if ((subframe==0) || (subframe==8) || (subframe==9)) - return(1); - else return(0); + case 3: + if ((subframe == 0) || (subframe == 8) || (subframe == 9)) + return (1); + else + return (0); - break; + break; - case 4: - if ((subframe==8) || (subframe==9)) - return(1); - else return(0); + case 4: + if ((subframe == 8) || (subframe == 9)) + return (1); + else + return (0); - break; + break; - case 5: - if (subframe==8) - return(1); - else return(0); + case 5: + if (subframe == 8) + return (1); + else + return (0); - break; + break; - case 6: - return(1); - break; + case 6: + return (1); + break; - default: - return(0); - } + default: + return (0); + } } -uint16_t get_nCCE_max(COMMON_channels_t *cc, int num_pdcch_symbols,int subframe) +uint16_t +get_nCCE_max(COMMON_channels_t * cc, int num_pdcch_symbols, int subframe) { - AssertFatal(cc!=NULL,"cc is null\n"); - return(getnCCE(cc,num_pdcch_symbols, - getmi(cc,subframe))); + AssertFatal(cc != NULL, "cc is null\n"); + return (getnCCE(cc, num_pdcch_symbols, getmi(cc, subframe))); } // Allocate the CCEs -int allocate_CCEs(int module_idP, - int CC_idP, - int subframeP, - int test_onlyP) -{ - int *CCE_table = RC.mac[module_idP]->CCE_table[CC_idP]; - nfapi_dl_config_request_body_t *DL_req = &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body; - nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; - nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[0]; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[0]; - int nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],1,subframeP); - int fCCE; - int i,j,idci; - int nCCE=0; - - LOG_D(MAC,"Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n",subframeP,test_onlyP,DL_req->number_pdu,DL_req->number_dci,HI_DCI0_req->number_of_dci); - DL_req->number_pdcch_ofdm_symbols=1; - -try_again: - init_CCE_table(module_idP,CC_idP); - nCCE=0; - - for (i=0,idci=0;i<DL_req->number_pdu;i++) { - // allocate DL common DCIs first - if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&& - (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type==2) - ) { - LOG_D(MAC,"Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - idci,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols); - - if (nCCE + (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) { - if (DL_req->number_pdcch_ofdm_symbols == 3) - goto failed; - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } - - // number of CCEs left can potentially hold this allocation - fCCE = get_nCCE_offset(CCE_table, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE_max, - 1, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti, - subframeP); - if (fCCE == -1) { - if (DL_req->number_pdcch_ofdm_symbols == 3) { - LOG_D(MAC,"subframe %d: Dropping Allocation for RNTI %x\n", - subframeP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti); - for (j=0;j<=i;j++){ - if (dl_config_pdu[j].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) - LOG_D(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - j,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.rnti, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.dci_format, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols); - } - //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); - goto failed; - } - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } // fCCE==-1 - - // the allocation is feasible, rnti rule passes - nCCE += dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level; - LOG_D(MAC,"Allocating at nCCE %d\n",fCCE); - if (test_onlyP == 0) { - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx=fCCE; - LOG_D(MAC,"Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n",subframeP,test_onlyP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,fCCE); - } - idci++; - } - } // for i = 0 ... num_DL_DCIs - - // no try to allocate UL DCIs - for (i=0;i<HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi;i++) { - - // allocate UL DCIs - if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) { - - LOG_D(MAC,"Trying to allocate format 0 DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - idci,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti,hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level, - nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols); - - if (nCCE + (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level) > nCCE_max) { - if (DL_req->number_pdcch_ofdm_symbols == 3) - goto failed; - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } - - // number of CCEs left can potentially hold this allocation - fCCE = get_nCCE_offset(CCE_table, - hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level, - nCCE_max, - 0, - hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti, - subframeP); - if (fCCE == -1) { - if (DL_req->number_pdcch_ofdm_symbols == 3) { - LOG_D(MAC,"subframe %d: Dropping Allocation for RNTI %x\n", - subframeP,hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti); - for (j=0;j<=i;j++){ - if (hi_dci0_pdu[j].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) - LOG_D(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - j,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.rnti, - hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.dci_format, - hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.aggregation_level, - nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols); - } - //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); - goto failed; - } - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } // fCCE==-1 - - // the allocation is feasible, rnti rule passes - nCCE += hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level; - LOG_D(MAC,"Allocating at nCCE %d\n",fCCE); - if (test_onlyP == 0) { - hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.cce_index=fCCE; - LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); - } - idci++; - } - } // for i = 0 ... num_UL_DCIs - - for (i=0;i<DL_req->number_pdu;i++) { - // allocate DL UE specific DCIs - if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&& - (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type==1)) { - LOG_D(MAC,"Trying to allocate DL UE-SPECIFIC DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - idci,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols); - - if (nCCE + (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) { - if (DL_req->number_pdcch_ofdm_symbols == 3) - goto failed; - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } - - // number of CCEs left can potentially hold this allocation - fCCE = get_nCCE_offset(CCE_table, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE_max, - 0, - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti, - subframeP); - if (fCCE == -1) { - if (DL_req->number_pdcch_ofdm_symbols == 3) { - LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n", - subframeP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti); - for (j=0;j<=i;j++){ - if (dl_config_pdu[j].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) - LOG_I(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - j,DL_req->number_dci+HI_DCI0_req->number_of_dci, - DL_req->number_dci,HI_DCI0_req->number_of_dci, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.rnti, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.dci_format, - dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols); - } - //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); - goto failed; - } - LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols); - - DL_req->number_pdcch_ofdm_symbols++; - nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP); - goto try_again; - } // fCCE==-1 - - // the allocation is feasible, rnti rule passes - nCCE += dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level; - LOG_D(MAC,"Allocating at nCCE %d\n",fCCE); - if (test_onlyP == 0) { - dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx=fCCE; - LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); - } - idci++; - } - } // for i = 0 ... num_DL_DCIs +int +allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP) +{ + int *CCE_table = RC.mac[module_idP]->CCE_table[CC_idP]; + nfapi_dl_config_request_body_t *DL_req = + &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body; + nfapi_hi_dci0_request_body_t *HI_DCI0_req = + &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &DL_req->dl_config_pdu_list[0]; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = + &HI_DCI0_req->hi_dci0_pdu_list[0]; + int nCCE_max = + get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP], 1, + subframeP); + int fCCE; + int i, j, idci; + int nCCE = 0; + + LOG_D(MAC, + "Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n", + subframeP, test_onlyP, DL_req->number_pdu, DL_req->number_dci, + HI_DCI0_req->number_of_dci); + DL_req->number_pdcch_ofdm_symbols = 1; + + try_again: + init_CCE_table(module_idP, CC_idP); + nCCE = 0; + + for (i = 0, idci = 0; i < DL_req->number_pdu; i++) { + // allocate DL common DCIs first + if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) + && (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == + 2)) { + LOG_D(MAC, + "Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + idci, DL_req->number_dci + HI_DCI0_req->number_of_dci, + DL_req->number_dci, HI_DCI0_req->number_of_dci, + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu[i].dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, nCCE, nCCE_max, + DL_req->number_pdcch_ofdm_symbols); + + if (nCCE + + (dl_config_pdu[i].dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level) > nCCE_max) { + if (DL_req->number_pdcch_ofdm_symbols == 3) + goto failed; + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } + // number of CCEs left can potentially hold this allocation + fCCE = get_nCCE_offset(CCE_table, + dl_config_pdu[i]. + dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, nCCE_max, 1, + dl_config_pdu[i]. + dci_dl_pdu.dci_dl_pdu_rel8.rnti, + subframeP); + if (fCCE == -1) { + if (DL_req->number_pdcch_ofdm_symbols == 3) { + LOG_D(MAC, + "subframe %d: Dropping Allocation for RNTI %x\n", + subframeP, + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8. + rnti); + for (j = 0; j <= i; j++) { + if (dl_config_pdu[j].pdu_type == + NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) + LOG_D(MAC, + "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + j, + DL_req->number_dci + + HI_DCI0_req->number_of_dci, + DL_req->number_dci, + HI_DCI0_req->number_of_dci, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8.dci_format, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, nCCE, nCCE_max, + DL_req->number_pdcch_ofdm_symbols); + } + //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); + goto failed; + } + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } // fCCE==-1 + + // the allocation is feasible, rnti rule passes + nCCE += + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level; + LOG_D(MAC, "Allocating at nCCE %d\n", fCCE); + if (test_onlyP == 0) { + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE; + LOG_D(MAC, + "Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n", + subframeP, test_onlyP, + dl_config_pdu[i].dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, fCCE); + } + idci++; + } + } // for i = 0 ... num_DL_DCIs + + // no try to allocate UL DCIs + for (i = 0; i < HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi; + i++) { + + // allocate UL DCIs + if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) { + + LOG_D(MAC, + "Trying to allocate format 0 DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + idci, DL_req->number_dci + HI_DCI0_req->number_of_dci, + DL_req->number_dci, HI_DCI0_req->number_of_dci, + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti, + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level, + nCCE, nCCE_max, DL_req->number_pdcch_ofdm_symbols); + + if (nCCE + + (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level) > + nCCE_max) { + if (DL_req->number_pdcch_ofdm_symbols == 3) + goto failed; + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } + // number of CCEs left can potentially hold this allocation + fCCE = get_nCCE_offset(CCE_table, + hi_dci0_pdu[i].dci_pdu. + dci_pdu_rel8.aggregation_level, + nCCE_max, 0, + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8. + rnti, subframeP); + if (fCCE == -1) { + if (DL_req->number_pdcch_ofdm_symbols == 3) { + LOG_D(MAC, + "subframe %d: Dropping Allocation for RNTI %x\n", + subframeP, + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti); + for (j = 0; j <= i; j++) { + if (hi_dci0_pdu[j].pdu_type == + NFAPI_HI_DCI0_DCI_PDU_TYPE) + LOG_D(MAC, + "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + j, + DL_req->number_dci + + HI_DCI0_req->number_of_dci, + DL_req->number_dci, + HI_DCI0_req->number_of_dci, + hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.rnti, + hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8. + dci_format, + hi_dci0_pdu[j].dci_pdu. + dci_pdu_rel8.aggregation_level, nCCE, + nCCE_max, + DL_req->number_pdcch_ofdm_symbols); + } + //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); + goto failed; + } + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } // fCCE==-1 + + // the allocation is feasible, rnti rule passes + nCCE += hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level; + LOG_D(MAC, "Allocating at nCCE %d\n", fCCE); + if (test_onlyP == 0) { + hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.cce_index = fCCE; + LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n", + subframeP, test_onlyP); + } + idci++; + } + } // for i = 0 ... num_UL_DCIs + + for (i = 0; i < DL_req->number_pdu; i++) { + // allocate DL UE specific DCIs + if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) + && (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == + 1)) { + LOG_D(MAC, + "Trying to allocate DL UE-SPECIFIC DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + idci, DL_req->number_dci + HI_DCI0_req->number_of_dci, + DL_req->number_dci, HI_DCI0_req->number_of_dci, + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu[i].dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level, nCCE, nCCE_max, + DL_req->number_pdcch_ofdm_symbols); + + if (nCCE + + (dl_config_pdu[i].dci_dl_pdu. + dci_dl_pdu_rel8.aggregation_level) > nCCE_max) { + if (DL_req->number_pdcch_ofdm_symbols == 3) + goto failed; + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } + // number of CCEs left can potentially hold this allocation + fCCE = get_nCCE_offset(CCE_table, + dl_config_pdu[i]. + dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, nCCE_max, 0, + dl_config_pdu[i]. + dci_dl_pdu.dci_dl_pdu_rel8.rnti, + subframeP); + if (fCCE == -1) { + if (DL_req->number_pdcch_ofdm_symbols == 3) { + LOG_I(MAC, + "subframe %d: Dropping Allocation for RNTI %x\n", + subframeP, + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8. + rnti); + for (j = 0; j <= i; j++) { + if (dl_config_pdu[j].pdu_type == + NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) + LOG_I(MAC, + "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + j, + DL_req->number_dci + + HI_DCI0_req->number_of_dci, + DL_req->number_dci, + HI_DCI0_req->number_of_dci, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8.dci_format, + dl_config_pdu[j]. + dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, nCCE, nCCE_max, + DL_req->number_pdcch_ofdm_symbols); + } + //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L); + goto failed; + } + LOG_D(MAC, + "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n", + DL_req->number_pdcch_ofdm_symbols); + + DL_req->number_pdcch_ofdm_symbols++; + nCCE_max = + get_nCCE_max(&RC.mac[module_idP]-> + common_channels[CC_idP], + DL_req->number_pdcch_ofdm_symbols, + subframeP); + goto try_again; + } // fCCE==-1 + + // the allocation is feasible, rnti rule passes + nCCE += + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level; + LOG_D(MAC, "Allocating at nCCE %d\n", fCCE); + if (test_onlyP == 0) { + dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE; + LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n", + subframeP, test_onlyP); + } + idci++; + } + } // for i = 0 ... num_DL_DCIs - return 0; + return 0; -failed: - return -1; + failed: + return -1; } /* @@ -2920,750 +3412,1046 @@ uint8_t get_ul_req_index(module_id_t module_idP, int CC_idP, sub_frame_t subfram } */ -nfapi_ul_config_request_pdu_t* has_ul_grant(module_id_t module_idP,int CC_idP,uint16_t absSFP,uint16_t rnti) -{ - nfapi_ul_config_request_body_t *ul_req; - nfapi_ul_config_request_pdu_t *ul_config_pdu; - - ul_req = &RC.mac[module_idP]->UL_req_tmp[CC_idP][absSFP%10].ul_config_request_body; - ul_config_pdu = &ul_req->ul_config_pdu_list[0]; - LOG_D(MAC,"Checking for rnti %x UL grant in subframeP %d (num pdu %d)\n",rnti,absSFP%10,ul_req->number_of_pdus); - - for (int i=0; i<ul_req->number_of_pdus;i++){ - LOG_D(MAC,"PDU %d : type %d,rnti %x\n",i,ul_config_pdu[i].pdu_type,rnti); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE)&& - (ul_config_pdu[i].uci_cqi_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE)&& - (ul_config_pdu[i].uci_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].uci_cqi_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE)&& - (ul_config_pdu[i].uci_cqi_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE) && - (ul_config_pdu[i].uci_cqi_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_uci_csi_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE)&& - (ul_config_pdu[i].ulsch_csi_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]); - } +nfapi_ul_config_request_pdu_t *has_ul_grant(module_id_t module_idP, + int CC_idP, uint16_t absSFP, + uint16_t rnti) +{ + nfapi_ul_config_request_body_t *ul_req; + nfapi_ul_config_request_pdu_t *ul_config_pdu; + + ul_req = + &RC.mac[module_idP]->UL_req_tmp[CC_idP][absSFP % + 10].ul_config_request_body; + ul_config_pdu = &ul_req->ul_config_pdu_list[0]; + LOG_D(MAC, + "Checking for rnti %x UL grant in subframeP %d (num pdu %d)\n", + rnti, absSFP % 10, ul_req->number_of_pdus); + + for (int i = 0; i < ul_req->number_of_pdus; i++) { + LOG_D(MAC, "PDU %d : type %d,rnti %x\n", i, + ul_config_pdu[i].pdu_type, rnti); + if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) + && (ul_config_pdu[i].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) + && (ul_config_pdu[i].ulsch_cqi_ri_pdu.ulsch_pdu. + ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) + && (ul_config_pdu[i].ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8. + rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE) + && (ul_config_pdu[i].ulsch_cqi_harq_ri_pdu. + ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + + if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE) + && (ul_config_pdu[i].uci_cqi_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) + && (ul_config_pdu[i].uci_sr_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) + && (ul_config_pdu[i].uci_harq_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE) + && (ul_config_pdu[i].uci_sr_harq_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE) + && (ul_config_pdu[i].uci_cqi_harq_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) + && (ul_config_pdu[i].uci_cqi_sr_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE) + && (ul_config_pdu[i].uci_cqi_sr_harq_pdu. + ue_information.ue_information_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE) + && (ul_config_pdu[i].ulsch_uci_csi_pdu. + ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE) + && (ul_config_pdu[i].ulsch_uci_harq_pdu. + ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + if ((ul_config_pdu[i].pdu_type == + NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE) + && (ul_config_pdu[i].ulsch_csi_uci_harq_pdu. + ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) + return (&ul_config_pdu[i]); + } - return(NULL); // no ul grant at all for this UE + return (NULL); // no ul grant at all for this UE } -boolean_t CCE_allocation_infeasible(int module_idP, - int CC_idP, - int format_flag, - int subframe, - int aggregation, - int rnti) +boolean_t +CCE_allocation_infeasible(int module_idP, + int CC_idP, + int format_flag, + int subframe, int aggregation, int rnti) { - nfapi_dl_config_request_body_t *DL_req = &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body; - nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; - nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; - int ret; - boolean_t res = FALSE; - - if (format_flag != 2) { // DL DCI - if (DL_req->number_pdu == MAX_NUM_DL_PDU) { - LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", - subframe, rnti); - } else { - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; - DL_req->number_pdu++; - LOG_D(MAC,"Subframe %d: Checking CCE feasibility format %d : (%x,%d) (%x,%d,%d)\n", - subframe,format_flag,rnti,aggregation, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type); - ret = allocate_CCEs(module_idP,CC_idP,subframe,0); - if (ret==-1) - res = TRUE; - DL_req->number_pdu--; - } - } - else { // ue-specific UL DCI - if (HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi == MAX_NUM_HI_DCI0_PDU) { - LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", - subframe, rnti); - } else { - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - HI_DCI0_req->number_of_dci++; - ret = allocate_CCEs(module_idP,CC_idP,subframe,0); - if (ret==-1) - res = TRUE; - HI_DCI0_req->number_of_dci--; + nfapi_dl_config_request_body_t *DL_req = + &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body; + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + nfapi_hi_dci0_request_body_t *HI_DCI0_req = + &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = + &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci + + HI_DCI0_req->number_of_hi]; + int ret; + boolean_t res = FALSE; + + if (format_flag != 2) { // DL DCI + if (DL_req->number_pdu == MAX_NUM_DL_PDU) { + LOG_W(MAC, + "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", + subframe, rnti); + } else { + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = + (format_flag == 0) ? 2 : 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + aggregation; + DL_req->number_pdu++; + LOG_D(MAC, + "Subframe %d: Checking CCE feasibility format %d : (%x,%d) (%x,%d,%d)\n", + subframe, format_flag, rnti, aggregation, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8. + aggregation_level, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type); + ret = allocate_CCEs(module_idP, CC_idP, subframe, 0); + if (ret == -1) + res = TRUE; + DL_req->number_pdu--; + } + } else { // ue-specific UL DCI + if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi == + MAX_NUM_HI_DCI0_PDU) { + LOG_W(MAC, + "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", + subframe, rnti); + } else { + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = + aggregation; + HI_DCI0_req->number_of_dci++; + ret = allocate_CCEs(module_idP, CC_idP, subframe, 0); + if (ret == -1) + res = TRUE; + HI_DCI0_req->number_of_dci--; + } } - } - return res; + return res; } -void extract_harq(module_id_t mod_idP,int CC_idP,int UE_id,frame_t frameP,sub_frame_t subframeP,void *harq_indication,int format) +void +extract_harq(module_id_t mod_idP, int CC_idP, int UE_id, + frame_t frameP, sub_frame_t subframeP, + void *harq_indication, int format) { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - rnti_t rnti = UE_RNTI(mod_idP,UE_id); - COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; - nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd; - nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd; - uint16_t num_ack_nak; - int numCC = UE_list->numactiveCCs[UE_id]; - int pCCid = UE_list->pCC_id[UE_id]; - int spatial_bundling = 0; - int tmode[5]; - int i,j; - uint8_t *pdu; + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + rnti_t rnti = UE_RNTI(mod_idP, UE_id); + COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; + nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd; + nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd; + uint16_t num_ack_nak; + int numCC = UE_list->numactiveCCs[UE_id]; + int pCCid = UE_list->pCC_id[UE_id]; + int spatial_bundling = 0; + int tmode[5]; + int i, j; + uint8_t *pdu; #ifdef Rel14 - AssertFatal(UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,"pucch_ConfigDedicated is null!\n"); - if ((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7) && - (UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13) && - (((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUCCH_r13) && - (format==0)) || - ((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUSCH_r13) && - (format==1)))) - spatial_bundling = 1; + AssertFatal(UE_list-> + UE_template[pCCid][UE_id].physicalConfigDedicated-> + pucch_ConfigDedicated != NULL, + "pucch_ConfigDedicated is null!\n"); + if ((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7) + && (UE_list->UE_template[pCCid][UE_id]. + physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13) + && + (((UE_list->UE_template[pCCid][UE_id]. + physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13-> + spatialBundlingPUCCH_r13) + && (format == 0)) + || + ((UE_list->UE_template[pCCid][UE_id]. + physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13-> + spatialBundlingPUSCH_r13) + && (format == 1)))) + spatial_bundling = 1; #endif - for (i=0;i<numCC;i++) tmode[i] = get_tmode(mod_idP,i,UE_id); - - if (cc->tdd_Config) { - harq_indication_tdd = (nfapi_harq_indication_tdd_rel13_t *)harq_indication; - // pdu = &harq_indication_tdd->harq_tb_n[0]; - - num_ack_nak = harq_indication_tdd->number_of_ack_nack; - - switch (harq_indication_tdd->mode) { - case 0: // Format 1a/b - AssertFatal(numCC==1,"numCC %d > 1, should not be using Format1a/b\n",numCC); - break; - case 1: // Channel Selection - break; - case 2: // Format 3 - break; - case 3: // Format 4 - break; - case 4: // Format 5 - break; - } - } - else { - harq_indication_fdd = (nfapi_harq_indication_fdd_rel13_t *)harq_indication; - num_ack_nak = harq_indication_fdd->number_of_ack_nack; - pdu = &harq_indication_fdd->harq_tb_n[0]; - - uint8_t harq_pid = ((10*frameP) + subframeP + 10236)&7; - - switch (harq_indication_fdd->mode) { - case 0: // Format 1a/b (10.1.2.1) - AssertFatal(numCC==1,"numCC %d > 1, should not be using Format1a/b\n",numCC); - if (tmode[0]==1 || tmode[0]==2 || tmode[0]==5 || tmode[0]==6 || tmode[0]==7) { // NOTE: have to handle the case of TM9-10 with 1 antenna port - // single ACK/NAK bit - AssertFatal(num_ack_nak==1,"num_ack_nak %d > 1 for 1 CC and single-layer transmission\n",num_ack_nak); - AssertFatal(sched_ctl->round[CC_idP][harq_pid]<8,"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",harq_pid,UE_id,rnti); - AssertFatal(pdu[0] == 1 || pdu[0] == 2 || pdu[0] == 4, - "Received ACK/NAK %d which is not 1 or 2 for harq_pid %d from UE %d/%x\n",pdu[0],harq_pid,UE_id,rnti); - LOG_D(MAC,"Received %d for harq_pid %d\n",pdu[0],harq_pid); - - if (pdu[0] == 1) { // ACK - sched_ctl->round[CC_idP][harq_pid]=8; // release HARQ process - sched_ctl->tbcnt[CC_idP][harq_pid]=0; - } - else if (pdu[0] == 2 || pdu[0] == 4) // NAK (treat DTX as NAK) - sched_ctl->round[CC_idP][harq_pid]++; // increment round - } - else { - // one or two ACK/NAK bits - AssertFatal(num_ack_nak>2,"num_ack_nak %d > 2 for 1 CC and TM3/4/8/9/10\n",num_ack_nak); - if ((num_ack_nak==2) && (sched_ctl->round[CC_idP][harq_pid]<8) && (sched_ctl->tbcnt[CC_idP][harq_pid]==1) && (pdu[0] == 1) && (pdu[1] == 1)) { - sched_ctl->round[CC_idP][harq_pid]=8; - sched_ctl->tbcnt[CC_idP][harq_pid]=0; - } - if ((num_ack_nak==2) && (sched_ctl->round[CC_idP][harq_pid]<8) && (sched_ctl->tbcnt[CC_idP][harq_pid]==1) && (pdu[0] == 2) && (pdu[1] == 2)) - sched_ctl->round[CC_idP][harq_pid]++; - else if (((num_ack_nak==2) && (sched_ctl->round[CC_idP][harq_pid]<8) && (sched_ctl->tbcnt[0][harq_pid]==2) && (pdu[0] == 1) && (pdu[1] == 2)) || - ((num_ack_nak==2) && (sched_ctl->round[CC_idP][harq_pid]<8) && (sched_ctl->tbcnt[CC_idP][harq_pid]==2) && (pdu[0] == 2) && (pdu[1] == 1))) { - sched_ctl->round[CC_idP][harq_pid]++; - sched_ctl->tbcnt[CC_idP][harq_pid]=1; - } - else if ((num_ack_nak==2) && (sched_ctl->round[CC_idP][harq_pid]<8) && (sched_ctl->tbcnt[CC_idP][harq_pid]==2) && (pdu[0] == 2) && (pdu[1] == 2)) - sched_ctl->round[CC_idP][harq_pid]++; - else AssertFatal(1==0,"Illegal ACK/NAK/round combination (%d,%d,%d,%d,%d) for harq_pid %d, UE %d/%x\n", - num_ack_nak,sched_ctl->round[CC_idP][harq_pid],sched_ctl->round[CC_idP][harq_pid],pdu[0],pdu[1], harq_pid,UE_id, - rnti); - } - break; - case 1: // FDD Channel Selection (10.1.2.2.1), must be received for 2 serving cells - AssertFatal(numCC==2,"Should not receive harq indication with channel selection with %d active CCs\n", - numCC); - - if ((num_ack_nak == 2) && (sched_ctl->round[pCCid][harq_pid]<8) && (sched_ctl->round[1-pCCid][harq_pid]<8) && (sched_ctl->tbcnt[pCCid][harq_pid]==1) && (sched_ctl->tbcnt[1-pCCid][harq_pid]==1)) { - AssertFatal(pdu[0]<=3,"pdu[0] %d is not ACK/NAK/DTX\n",pdu[0]); - AssertFatal(pdu[1]<=3,"pdu[1] %d is not ACK/NAK/DTX\n",pdu[1]); - if (pdu[0] == 1) sched_ctl->round[pCCid][harq_pid]=8; - else sched_ctl->round[pCCid][harq_pid]++; - if (pdu[1] == 1) sched_ctl->round[1-pCCid][harq_pid]=8; - else sched_ctl->round[1-pCCid][harq_pid]++; - } // A=2 - else if ((num_ack_nak == 3) && (sched_ctl->round[pCCid][harq_pid]<8) && (sched_ctl->tbcnt[pCCid][harq_pid]==2) && (sched_ctl->round[1-pCCid][harq_pid]<8) && (sched_ctl->tbcnt[1-pCCid][harq_pid]==1)) { - AssertFatal(pdu[0]<=3,"pdu[0] %d is not ACK/NAK/DTX\n",pdu[0]); - AssertFatal(pdu[1]<=3,"pdu[1] %d is not ACK/NAK/DTX\n",pdu[1]); - AssertFatal(pdu[2]<=3,"pdu[2] %d is not ACK/NAK/DTX\n",pdu[2]); - AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 2,"sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",pCCid,harq_pid,UE_id,rnti); - AssertFatal(sched_ctl->tbcnt[1-pCCid][harq_pid] == 1,"sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",1-pCCid,harq_pid,UE_id,rnti); - if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK - sched_ctl->round[pCCid][harq_pid]=8; - sched_ctl->tbcnt[pCCid][harq_pid]=0; - } - else if (((pdu[0] == 2) && (pdu[1] == 1))|| - ((pdu[0] == 1) && (pdu[1] == 2))){ - sched_ctl->round[pCCid][harq_pid]++; - sched_ctl->tbcnt[pCCid][harq_pid]=1; - } - else - sched_ctl->round[pCCid][harq_pid]++; - - if (pdu[2] == 1) sched_ctl->round[1-pCCid][harq_pid]=8; - else sched_ctl->round[1-pCCid][harq_pid]++; - } // A=3 primary cell has 2 TBs - else if ((num_ack_nak == 3) && (sched_ctl->round[1-pCCid][harq_pid]<8) && (sched_ctl->round[pCCid][harq_pid]<8) && (sched_ctl->tbcnt[1-pCCid][harq_pid]==2) && (sched_ctl->tbcnt[pCCid][harq_pid]==1)) { - AssertFatal(pdu[0]<=3,"pdu[0] %d is not ACK/NAK/DTX\n",pdu[0]); - AssertFatal(pdu[1]<=3,"pdu[1] %d is not ACK/NAK/DTX\n",pdu[1]); - AssertFatal(pdu[2]<=3,"pdu[2] %d is not ACK/NAK/DTX\n",pdu[2]); - AssertFatal(sched_ctl->tbcnt[1-pCCid][harq_pid] == 2,"sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",1-pCCid,harq_pid,UE_id,rnti); - AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 1,"sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",pCCid,harq_pid,UE_id,rnti); - if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK - sched_ctl->round[1-pCCid][harq_pid]=8; - sched_ctl->tbcnt[1-pCCid][harq_pid]=0; - } - else if (((pdu[0] >= 2) && (pdu[1] == 1))|| - ((pdu[0] == 1) && (pdu[1] >= 2))){ // one ACK - sched_ctl->round[1-pCCid][harq_pid]++; - sched_ctl->tbcnt[1-pCCid][harq_pid]=1; - } - else // both NAK/DTX - sched_ctl->round[1-pCCid][harq_pid]++; - - if (pdu[2] == 1) sched_ctl->round[pCCid][harq_pid]=8; - else sched_ctl->round[pCCid][harq_pid]++; - } // A=3 secondary cell has 2 TBs + for (i = 0; i < numCC; i++) + tmode[i] = get_tmode(mod_idP, i, UE_id); + + if (cc->tdd_Config) { + harq_indication_tdd = + (nfapi_harq_indication_tdd_rel13_t *) harq_indication; + // pdu = &harq_indication_tdd->harq_tb_n[0]; + + num_ack_nak = harq_indication_tdd->number_of_ack_nack; + + switch (harq_indication_tdd->mode) { + case 0: // Format 1a/b + AssertFatal(numCC == 1, + "numCC %d > 1, should not be using Format1a/b\n", + numCC); + break; + case 1: // Channel Selection + break; + case 2: // Format 3 + break; + case 3: // Format 4 + break; + case 4: // Format 5 + break; + } + } else { + harq_indication_fdd = + (nfapi_harq_indication_fdd_rel13_t *) harq_indication; + num_ack_nak = harq_indication_fdd->number_of_ack_nack; + pdu = &harq_indication_fdd->harq_tb_n[0]; + + uint8_t harq_pid = ((10 * frameP) + subframeP + 10236) & 7; + + switch (harq_indication_fdd->mode) { + case 0: // Format 1a/b (10.1.2.1) + AssertFatal(numCC == 1, + "numCC %d > 1, should not be using Format1a/b\n", + numCC); + if (tmode[0] == 1 || tmode[0] == 2 || tmode[0] == 5 || tmode[0] == 6 || tmode[0] == 7) { // NOTE: have to handle the case of TM9-10 with 1 antenna port + // single ACK/NAK bit + AssertFatal(num_ack_nak == 1, + "num_ack_nak %d > 1 for 1 CC and single-layer transmission\n", + num_ack_nak); + AssertFatal(sched_ctl->round[CC_idP][harq_pid] < 8, + "Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n", + harq_pid, UE_id, rnti); + AssertFatal(pdu[0] == 1 || pdu[0] == 2 + || pdu[0] == 4, + "Received ACK/NAK %d which is not 1 or 2 for harq_pid %d from UE %d/%x\n", + pdu[0], harq_pid, UE_id, rnti); + LOG_D(MAC, "Received %d for harq_pid %d\n", pdu[0], + harq_pid); + + if (pdu[0] == 1) { // ACK + sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process + sched_ctl->tbcnt[CC_idP][harq_pid] = 0; + } else if (pdu[0] == 2 || pdu[0] == 4) // NAK (treat DTX as NAK) + sched_ctl->round[CC_idP][harq_pid]++; // increment round + } else { + // one or two ACK/NAK bits + AssertFatal(num_ack_nak > 2, + "num_ack_nak %d > 2 for 1 CC and TM3/4/8/9/10\n", + num_ack_nak); + if ((num_ack_nak == 2) + && (sched_ctl->round[CC_idP][harq_pid] < 8) + && (sched_ctl->tbcnt[CC_idP][harq_pid] == 1) + && (pdu[0] == 1) && (pdu[1] == 1)) { + sched_ctl->round[CC_idP][harq_pid] = 8; + sched_ctl->tbcnt[CC_idP][harq_pid] = 0; + } + if ((num_ack_nak == 2) + && (sched_ctl->round[CC_idP][harq_pid] < 8) + && (sched_ctl->tbcnt[CC_idP][harq_pid] == 1) + && (pdu[0] == 2) && (pdu[1] == 2)) + sched_ctl->round[CC_idP][harq_pid]++; + else if (((num_ack_nak == 2) + && (sched_ctl->round[CC_idP][harq_pid] < 8) + && (sched_ctl->tbcnt[0][harq_pid] == 2) + && (pdu[0] == 1) && (pdu[1] == 2)) + || ((num_ack_nak == 2) + && (sched_ctl->round[CC_idP][harq_pid] < 8) + && (sched_ctl->tbcnt[CC_idP][harq_pid] == 2) + && (pdu[0] == 2) && (pdu[1] == 1))) { + sched_ctl->round[CC_idP][harq_pid]++; + sched_ctl->tbcnt[CC_idP][harq_pid] = 1; + } else if ((num_ack_nak == 2) + && (sched_ctl->round[CC_idP][harq_pid] < 8) + && (sched_ctl->tbcnt[CC_idP][harq_pid] == 2) + && (pdu[0] == 2) && (pdu[1] == 2)) + sched_ctl->round[CC_idP][harq_pid]++; + else + AssertFatal(1 == 0, + "Illegal ACK/NAK/round combination (%d,%d,%d,%d,%d) for harq_pid %d, UE %d/%x\n", + num_ack_nak, + sched_ctl->round[CC_idP][harq_pid], + sched_ctl->round[CC_idP][harq_pid], pdu[0], + pdu[1], harq_pid, UE_id, rnti); + } + break; + case 1: // FDD Channel Selection (10.1.2.2.1), must be received for 2 serving cells + AssertFatal(numCC == 2, + "Should not receive harq indication with channel selection with %d active CCs\n", + numCC); + + if ((num_ack_nak == 2) + && (sched_ctl->round[pCCid][harq_pid] < 8) + && (sched_ctl->round[1 - pCCid][harq_pid] < 8) + && (sched_ctl->tbcnt[pCCid][harq_pid] == 1) + && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1)) { + AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n", + pdu[0]); + AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n", + pdu[1]); + if (pdu[0] == 1) + sched_ctl->round[pCCid][harq_pid] = 8; + else + sched_ctl->round[pCCid][harq_pid]++; + if (pdu[1] == 1) + sched_ctl->round[1 - pCCid][harq_pid] = 8; + else + sched_ctl->round[1 - pCCid][harq_pid]++; + } // A=2 + else if ((num_ack_nak == 3) + && (sched_ctl->round[pCCid][harq_pid] < 8) + && (sched_ctl->tbcnt[pCCid][harq_pid] == 2) + && (sched_ctl->round[1 - pCCid][harq_pid] < 8) + && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1)) { + AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n", + pdu[0]); + AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n", + pdu[1]); + AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n", + pdu[2]); + AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 2, + "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n", + pCCid, harq_pid, UE_id, rnti); + AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1, + "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n", + 1 - pCCid, harq_pid, UE_id, rnti); + if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK + sched_ctl->round[pCCid][harq_pid] = 8; + sched_ctl->tbcnt[pCCid][harq_pid] = 0; + } else if (((pdu[0] == 2) && (pdu[1] == 1)) || + ((pdu[0] == 1) && (pdu[1] == 2))) { + sched_ctl->round[pCCid][harq_pid]++; + sched_ctl->tbcnt[pCCid][harq_pid] = 1; + } else + sched_ctl->round[pCCid][harq_pid]++; + + if (pdu[2] == 1) + sched_ctl->round[1 - pCCid][harq_pid] = 8; + else + sched_ctl->round[1 - pCCid][harq_pid]++; + } // A=3 primary cell has 2 TBs + else if ((num_ack_nak == 3) + && (sched_ctl->round[1 - pCCid][harq_pid] < 8) + && (sched_ctl->round[pCCid][harq_pid] < 8) + && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2) + && (sched_ctl->tbcnt[pCCid][harq_pid] == 1)) { + AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n", + pdu[0]); + AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n", + pdu[1]); + AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n", + pdu[2]); + AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2, + "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n", + 1 - pCCid, harq_pid, UE_id, rnti); + AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 1, + "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n", + pCCid, harq_pid, UE_id, rnti); + if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK + sched_ctl->round[1 - pCCid][harq_pid] = 8; + sched_ctl->tbcnt[1 - pCCid][harq_pid] = 0; + } else if (((pdu[0] >= 2) && (pdu[1] == 1)) + || ((pdu[0] == 1) && (pdu[1] >= 2))) { // one ACK + sched_ctl->round[1 - pCCid][harq_pid]++; + sched_ctl->tbcnt[1 - pCCid][harq_pid] = 1; + } else // both NAK/DTX + sched_ctl->round[1 - pCCid][harq_pid]++; + + if (pdu[2] == 1) + sched_ctl->round[pCCid][harq_pid] = 8; + else + sched_ctl->round[pCCid][harq_pid]++; + } // A=3 secondary cell has 2 TBs #if MAX_NUM_CCs>1 - else if ((num_ack_nak == 4) && (sched_ctl->round[0][harq_pid]<8) && (sched_ctl->round[1][harq_pid]<8) && (sched_ctl->tbcnt[1-pCCid][harq_pid]==2) && (sched_ctl->tbcnt[pCCid][harq_pid]==2)) { - AssertFatal(pdu[0]<=3,"pdu[0] %d is not ACK/NAK/DTX\n",pdu[0]); - AssertFatal(pdu[1]<=3,"pdu[1] %d is not ACK/NAK/DTX\n",pdu[1]); - AssertFatal(pdu[2]<=3,"pdu[2] %d is not ACK/NAK/DTX\n",pdu[2]); - AssertFatal(pdu[3]<=3,"pdu[3] %d is not ACK/NAK/DTX\n",pdu[3]); - AssertFatal(sched_ctl->tbcnt[0][harq_pid] == 2,"sched_ctl->tbcnt[0][%d] != 2 for UE %d/%x\n",harq_pid,UE_id,rnti); - AssertFatal(sched_ctl->tbcnt[1][harq_pid] == 2,"sched_ctl->tbcnt[1][%d] != 2 for UE %d/%x\n",harq_pid,UE_id,rnti); - if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK - sched_ctl->round[0][harq_pid]=8; - sched_ctl->tbcnt[0][harq_pid]=0; - } - else if (((pdu[0] >= 2) && (pdu[1] == 1))|| - ((pdu[0] == 1) && (pdu[1] >= 2))){ // one ACK - sched_ctl->round[0][harq_pid]++; - sched_ctl->tbcnt[0][harq_pid]=1; - } - else // both NAK/DTX - sched_ctl->round[0][harq_pid]++; - - if ((pdu[2] == 1) && (pdu[3] == 1)) { // both ACK - sched_ctl->round[1][harq_pid]=8; - sched_ctl->tbcnt[1][harq_pid]=0; - } - else if (((pdu[2] >= 2) && (pdu[3] == 1))|| - ((pdu[2] == 1) && (pdu[3] >= 2))){ // one ACK - sched_ctl->round[1][harq_pid]++; - sched_ctl->tbcnt[1][harq_pid]=1; - } - else // both NAK/DTX - sched_ctl->round[1][harq_pid]++; - } // A=4 both serving cells have 2 TBs + else if ((num_ack_nak == 4) + && (sched_ctl->round[0][harq_pid] < 8) + && (sched_ctl->round[1][harq_pid] < 8) + && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2) + && (sched_ctl->tbcnt[pCCid][harq_pid] == 2)) { + AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n", + pdu[0]); + AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n", + pdu[1]); + AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n", + pdu[2]); + AssertFatal(pdu[3] <= 3, "pdu[3] %d is not ACK/NAK/DTX\n", + pdu[3]); + AssertFatal(sched_ctl->tbcnt[0][harq_pid] == 2, + "sched_ctl->tbcnt[0][%d] != 2 for UE %d/%x\n", + harq_pid, UE_id, rnti); + AssertFatal(sched_ctl->tbcnt[1][harq_pid] == 2, + "sched_ctl->tbcnt[1][%d] != 2 for UE %d/%x\n", + harq_pid, UE_id, rnti); + if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK + sched_ctl->round[0][harq_pid] = 8; + sched_ctl->tbcnt[0][harq_pid] = 0; + } else if (((pdu[0] >= 2) && (pdu[1] == 1)) + || ((pdu[0] == 1) && (pdu[1] >= 2))) { // one ACK + sched_ctl->round[0][harq_pid]++; + sched_ctl->tbcnt[0][harq_pid] = 1; + } else // both NAK/DTX + sched_ctl->round[0][harq_pid]++; + + if ((pdu[2] == 1) && (pdu[3] == 1)) { // both ACK + sched_ctl->round[1][harq_pid] = 8; + sched_ctl->tbcnt[1][harq_pid] = 0; + } else if (((pdu[2] >= 2) && (pdu[3] == 1)) + || ((pdu[2] == 1) && (pdu[3] >= 2))) { // one ACK + sched_ctl->round[1][harq_pid]++; + sched_ctl->tbcnt[1][harq_pid] = 1; + } else // both NAK/DTX + sched_ctl->round[1][harq_pid]++; + } // A=4 both serving cells have 2 TBs #endif - break; - case 2: // Format 3 - AssertFatal(numCC>2,"Should not receive harq indication with FDD format 3 with %d < 3 active CCs\n", - numCC); - for (i=0,j=0;i<numCC;i++) { - if ((sched_ctl->round[i][harq_pid]<8)) { - if (tmode[i]==1 || tmode[i]==2 || tmode[0]==5 || tmode[0]==6 || tmode[0]==7) { - if (pdu[j] == 1) { - sched_ctl->round[i][harq_pid]=8; - sched_ctl->tbcnt[i][harq_pid]=0; - } - else if (pdu[j] == 2) sched_ctl->round[i][harq_pid]++; - else AssertFatal(1==0,"Illegal harq_ack value for CC %d harq_pid %d (%d) UE %d/%x\n", - i,harq_pid,pdu[j],UE_id,rnti); - j++; - } - else if (spatial_bundling == 0) { - if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 1) && (pdu[j+1]==1)) { - sched_ctl->round[i][harq_pid]=8; - sched_ctl->tbcnt[i][harq_pid]=0; - } - else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 1) && (pdu[j+1]==2)) { - sched_ctl->round[i][harq_pid]++; - sched_ctl->tbcnt[i][harq_pid]=1; - } - else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 2) && (pdu[j+1]==1)) { - sched_ctl->round[i][harq_pid]++; - sched_ctl->tbcnt[i][harq_pid]=1; - } - else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 2) && (pdu[j+1]==2)) { - sched_ctl->round[i][harq_pid]++; - } - else AssertFatal(1==0,"Illegal combination for CC %d harq_pid %d (%d,%d,%d) UE %d/%x\n", - i,harq_pid,sched_ctl->tbcnt[i][harq_pid],pdu[j],pdu[j+1],UE_id,rnti); - j+=2; - } - else if (spatial_bundling == 1) { - if (pdu[j] == 1) { - sched_ctl->round[i][harq_pid]=8; - sched_ctl->tbcnt[i][harq_pid]=0; - } - else if (pdu[j] == 2) { - sched_ctl->round[i][harq_pid]++; - } - else AssertFatal(1==0,"Illegal hack_nak value %d for CC %d harq_pid %d UE %d/%x\n", - pdu[j],i,harq_pid,UE_id,rnti); - j++; - } - else AssertFatal(1==0,"Illegal value for spatial_bundling %d\n",spatial_bundling); - } - } - break; - case 3: // Format 4 - AssertFatal(1==0,"Should not receive harq indication with Format 4\n"); - break; - case 4: // Format 5 - AssertFatal(1==0,"Should not receive harq indication with Format 5\n"); - break; + break; + case 2: // Format 3 + AssertFatal(numCC > 2, + "Should not receive harq indication with FDD format 3 with %d < 3 active CCs\n", + numCC); + for (i = 0, j = 0; i < numCC; i++) { + if ((sched_ctl->round[i][harq_pid] < 8)) { + if (tmode[i] == 1 || tmode[i] == 2 || tmode[0] == 5 + || tmode[0] == 6 || tmode[0] == 7) { + if (pdu[j] == 1) { + sched_ctl->round[i][harq_pid] = 8; + sched_ctl->tbcnt[i][harq_pid] = 0; + } else if (pdu[j] == 2) + sched_ctl->round[i][harq_pid]++; + else + AssertFatal(1 == 0, + "Illegal harq_ack value for CC %d harq_pid %d (%d) UE %d/%x\n", + i, harq_pid, pdu[j], UE_id, rnti); + j++; + } else if (spatial_bundling == 0) { + if ((sched_ctl->tbcnt[i][harq_pid] == 2) + && (pdu[j] == 1) && (pdu[j + 1] == 1)) { + sched_ctl->round[i][harq_pid] = 8; + sched_ctl->tbcnt[i][harq_pid] = 0; + } else if ((sched_ctl->tbcnt[i][harq_pid] == 2) + && (pdu[j] == 1) && (pdu[j + 1] == 2)) { + sched_ctl->round[i][harq_pid]++; + sched_ctl->tbcnt[i][harq_pid] = 1; + } else if ((sched_ctl->tbcnt[i][harq_pid] == 2) + && (pdu[j] == 2) && (pdu[j + 1] == 1)) { + sched_ctl->round[i][harq_pid]++; + sched_ctl->tbcnt[i][harq_pid] = 1; + } else if ((sched_ctl->tbcnt[i][harq_pid] == 2) + && (pdu[j] == 2) && (pdu[j + 1] == 2)) { + sched_ctl->round[i][harq_pid]++; + } else + AssertFatal(1 == 0, + "Illegal combination for CC %d harq_pid %d (%d,%d,%d) UE %d/%x\n", + i, harq_pid, + sched_ctl->tbcnt[i][harq_pid], + pdu[j], pdu[j + 1], UE_id, rnti); + j += 2; + } else if (spatial_bundling == 1) { + if (pdu[j] == 1) { + sched_ctl->round[i][harq_pid] = 8; + sched_ctl->tbcnt[i][harq_pid] = 0; + } else if (pdu[j] == 2) { + sched_ctl->round[i][harq_pid]++; + } else + AssertFatal(1 == 0, + "Illegal hack_nak value %d for CC %d harq_pid %d UE %d/%x\n", + pdu[j], i, harq_pid, UE_id, rnti); + j++; + } else + AssertFatal(1 == 0, + "Illegal value for spatial_bundling %d\n", + spatial_bundling); + } + } + break; + case 3: // Format 4 + AssertFatal(1 == 0, + "Should not receive harq indication with Format 4\n"); + break; + case 4: // Format 5 + AssertFatal(1 == 0, + "Should not receive harq indication with Format 5\n"); + break; + } } - } } -void extract_pucch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP,uint8_t *pdu, uint8_t length) +void +extract_pucch_csi(module_id_t mod_idP, int CC_idP, int UE_id, + frame_t frameP, sub_frame_t subframeP, + uint8_t * pdu, uint8_t length) { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - COMMON_channels_t *cc=&RC.mac[mod_idP]->common_channels[CC_idP]; - struct CQI_ReportPeriodic *cqi_ReportPeriodic; - int no_pmi; - uint8_t Ltab[6] = {0,2,4,4,4,4}; - uint8_t Jtab[6] = {0,2,2,3,4,4}; - int feedback_cnt; - - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL,"cqi_ReportConfig is null for UE %d\n",UE_id); - AssertFatal((cqi_ReportPeriodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic)!=NULL, - "cqi_ReportPeriodic is null for UE %d\n",UE_id); - - // determine feedback mode - AssertFatal(cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_NOTHING, - "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n"); - AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING, - "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n"); - - uint16_t Npd,N_OFFSET_CQI; - int H,K,bandwidth_part,L,Lmask; - int ri = sched_ctl->periodic_ri_received[CC_idP]; - - get_csi_params(cc,cqi_ReportPeriodic,&Npd,&N_OFFSET_CQI,&H); - K =(H-1)/Jtab[cc->mib->message.dl_Bandwidth]; - L = Ltab[cc->mib->message.dl_Bandwidth]; - Lmask =L-1; - feedback_cnt = (((frameP*10)+subframeP)/Npd)%H; - - if (feedback_cnt>0) bandwidth_part = (feedback_cnt-1)%K; - else bandwidth_part = 0; - - switch(get_tmode(mod_idP,CC_idP,UE_id)) { - case 1: - case 2: - case 3: - case 7: - no_pmi=1; - break; - case 4: - case 5: - case 6: - no_pmi=0; - break; - default: - // note: need to check TM8-10 without PMI/RI or with 1 antenna port (see Section 5.2.3.3.1 from 36.213) - no_pmi=0; - } - - if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) || - (feedback_cnt==0)){ - // Note: This implements only Tables: 5.3.3.1-1,5.3.3.1-1A and 5.3.3.1-2 from 36.213 (1,2,4 antenna ports Wideband CQI/PMI) + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; + struct CQI_ReportPeriodic *cqi_ReportPeriodic; + int no_pmi; + uint8_t Ltab[6] = { 0, 2, 4, 4, 4, 4 }; + uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 }; + int feedback_cnt; + + AssertFatal(UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated != NULL, + "physicalConfigDedicated is null for UE %d\n", UE_id); + AssertFatal(UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + cqi_ReportConfig != NULL, + "cqi_ReportConfig is null for UE %d\n", UE_id); + AssertFatal((cqi_ReportPeriodic = + UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + cqi_ReportConfig->cqi_ReportPeriodic) != NULL, + "cqi_ReportPeriodic is null for UE %d\n", UE_id); + + // determine feedback mode + AssertFatal(cqi_ReportPeriodic->present != + CQI_ReportPeriodic_PR_NOTHING, + "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n"); + AssertFatal(cqi_ReportPeriodic->choice. + setup.cqi_FormatIndicatorPeriodic.present != + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING, + "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n"); + + uint16_t Npd, N_OFFSET_CQI; + int H, K, bandwidth_part, L, Lmask; + int ri = sched_ctl->periodic_ri_received[CC_idP]; + + get_csi_params(cc, cqi_ReportPeriodic, &Npd, &N_OFFSET_CQI, &H); + K = (H - 1) / Jtab[cc->mib->message.dl_Bandwidth]; + L = Ltab[cc->mib->message.dl_Bandwidth]; + Lmask = L - 1; + feedback_cnt = (((frameP * 10) + subframeP) / Npd) % H; + + if (feedback_cnt > 0) + bandwidth_part = (feedback_cnt - 1) % K; + else + bandwidth_part = 0; - if (no_pmi == 1) { // get spatial_diffcqi if needed - sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0]&0xF; - sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7; - } - else if ((cc->p_eNB==2) && (ri==1)) { - // p=2 Rank 1 wideband CQI/PMI 6 bits - sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0]&0xF; - sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0]>>4)&3; - } - else if ((cc->p_eNB==2) && (ri>1)) { - // p=2 Rank 2 wideband CQI/PMI 8 bits - sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0]&0xF; - sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7; - sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0]>>7)&1; + switch (get_tmode(mod_idP, CC_idP, UE_id)) { + case 1: + case 2: + case 3: + case 7: + no_pmi = 1; + break; + case 4: + case 5: + case 6: + no_pmi = 0; + break; + default: + // note: need to check TM8-10 without PMI/RI or with 1 antenna port (see Section 5.2.3.3.1 from 36.213) + no_pmi = 0; } - else if ((cc->p_eNB==4) && (ri==1)) { - // p=4 Rank 1 wideband CQI/PMI 8 bits - sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0]&0xF; - sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0]>>4)&0x0F; + if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic. + present == + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) + || (feedback_cnt == 0)) { + // Note: This implements only Tables: 5.3.3.1-1,5.3.3.1-1A and 5.3.3.1-2 from 36.213 (1,2,4 antenna ports Wideband CQI/PMI) + + if (no_pmi == 1) { // get spatial_diffcqi if needed + sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF; + sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = + (pdu[0] >> 4) & 7; + } else if ((cc->p_eNB == 2) && (ri == 1)) { + // p=2 Rank 1 wideband CQI/PMI 6 bits + sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF; + sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 4) & 3; + } else if ((cc->p_eNB == 2) && (ri > 1)) { + // p=2 Rank 2 wideband CQI/PMI 8 bits + sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF; + sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = + (pdu[0] >> 4) & 7; + sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 1; + } else if ((cc->p_eNB == 4) && (ri == 1)) { + // p=4 Rank 1 wideband CQI/PMI 8 bits + sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF; + sched_ctl->periodic_wideband_pmi[CC_idP] = + (pdu[0] >> 4) & 0x0F; + + } else if ((cc->p_eNB == 4) && (ri > 1)) { + // p=4 Rank 2 wideband CQI/PMI 11 bits + sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF; + sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = + (pdu[0] >> 4) & 7; + sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 0xF; + } else + AssertFatal(1 == 0, + "illegal combination p %d, ri %d, no_pmi %d\n", + cc->p_eNB, ri, no_pmi); + } else if (cqi_ReportPeriodic->choice. + setup.cqi_FormatIndicatorPeriodic.present == + CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) + { + // This is Table 5.2.3.3.2-2 for 36.213 + if (ri == 1) { + //4+Ltab[cc->mib->message.dl_Bandwidth] bits + sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part * L) + + ((pdu[0] >> 4) & + Lmask)] = + pdu[0] & 0xF; + } else if (ri > 1) { + //7+Ltab[cc->mib->message.dl_Bandwidth] bits; + sched_ctl-> + periodic_subband_spatial_diffcqi[CC_idP][(bandwidth_part * + L) + + ((pdu[0] >> 7) & + Lmask)] = + (pdu[0] >> 4) & 7; + sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part * L) + + ((pdu[0] >> 7) & + Lmask)] = + pdu[0] & 0xF; + } } - else if ((cc->p_eNB==4) && (ri>1)) { - // p=4 Rank 2 wideband CQI/PMI 11 bits - sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0]&0xF; - sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7; - sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0]>>7)&0xF; - } - else AssertFatal(1==0,"illegal combination p %d, ri %d, no_pmi %d\n",cc->p_eNB,ri,no_pmi); - } - else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) { - // This is Table 5.2.3.3.2-2 for 36.213 - if (ri==1) { - //4+Ltab[cc->mib->message.dl_Bandwidth] bits - sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part*L)+((pdu[0]>>4)&Lmask)] = pdu[0]&0xF; - } - else if (ri>1) { - //7+Ltab[cc->mib->message.dl_Bandwidth] bits; - sched_ctl->periodic_subband_spatial_diffcqi[CC_idP][(bandwidth_part*L)+((pdu[0]>>7)&Lmask)] = (pdu[0]>>4)&7; - sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part*L)+((pdu[0]>>7)&Lmask)] = pdu[0]&0xF; - } - } } -void extract_pusch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP,uint8_t *pdu, uint8_t length) -{ - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - int Ntab[6] = {0,4,7,9,10,13}; - int Ntab_uesel[6] = {0,8,13,17,19,25}; - int Ltab_uesel[6] = {0,6,9,13,15,18}; - int Mtab_uesel[6] = {0,1,3,5,6,6}; - int v[6]; - int i; - uint64_t p = *(uint64_t*)pdu; - int curbyte, curbit; - CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic; - - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL,"cqi_ReportConfig is null for UE %d\n",UE_id); - AssertFatal((cqi_ReportModeAperiodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic)!=NULL, - "cqi_ReportModeAperiodic is null for UE %d\n",UE_id); - - int N = Ntab[cc->mib->message.dl_Bandwidth]; - int tmode = get_tmode(mod_idP,CC_idP,UE_id); - int ri = sched_ctl->aperiodic_ri_received[CC_idP]; - int r,diffcqi0=0,diffcqi1=0,pmi_uesel=0; - int bw = cc->mib->message.dl_Bandwidth; - int m; - - switch(*cqi_ReportModeAperiodic) { - case CQI_ReportModeAperiodic_rm12: - AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n"); - // wideband multiple PMI (TM4/6), Table 5.2.2.6.1-1 (for TM4/6) - AssertFatal(tmode==4 || tmode==6 || tmode==8|| tmode==9 || tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm12\n",tmode); - if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213 - if ((ri==1) && (cc->p_eNB==2)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x03); - p>>=2; - } - } - if ((ri==2) && (cc->p_eNB==2)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=1; - } - } - if ((ri==1) && (cc->p_eNB==4)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x03); - p>>=4; - } - } - if ((ri==2) && (cc->p_eNB==4)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=4; - } - } - } // if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213 - else { - AssertFatal(1==0,"support for TM 8-10 to be done\n"); - } - - break; - case CQI_ReportModeAperiodic_rm20: - AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n"); - // UE-selected subband CQI no PMI (TM1/2/3/7) , Table 5.2.2.6.3-1 from 36.213 - AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm20\n",tmode); - - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - diffcqi0 = (uint8_t)(p&0x03); p>>=2; - r = (uint8_t)(p&((1>>Ltab_uesel[bw])-1)); - reverse_index(Ntab_uesel[bw],Mtab_uesel[bw],r,v); - for (m=0;m<Mtab_uesel[bw];m++) sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0; - break; - case CQI_ReportModeAperiodic_rm22: - AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n"); - // UE-selected subband CQI multiple PMI (TM4/6) Table 5.2.2.6.3-2 from 36.213 - - AssertFatal(tmode==4 || tmode==6 || tmode==8|| tmode==9 || tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm22\n",tmode); - - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - diffcqi0 = (uint8_t)(p&0x03); p>>=2; - - if (ri>1) { - sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - diffcqi1 = (uint8_t)(p&0x03); p>>=2; - } - r = (uint8_t)(p&((1>>Ltab_uesel[bw])-1)); p>>=Ltab_uesel[bw]; - reverse_index(Ntab_uesel[bw],Mtab_uesel[bw],r,v); - if ((ri==1)&&(cc->p_eNB==2)) { - pmi_uesel = p&0x3; p>>=2; - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x3; - } - else if ((ri==2)&&(cc->p_eNB==2)) { - pmi_uesel = p&0x1; p>>=1; - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x1; - } - else if (cc->p_eNB==4) { - pmi_uesel = p&0x0F; p>>=4; - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x0F; - } - for (m=0;m<Mtab_uesel[bw];m++) { - sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0; - if (ri>1) sched_ctl->aperiodic_subband_diffcqi1[CC_idP][v[m]] = diffcqi1; - sched_ctl->aperiodic_subband_pmi[CC_idP][v[m]] = pmi_uesel; - } - break; - case CQI_ReportModeAperiodic_rm30: - //subband CQI no PMI (TM1/2/3/7) - AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm30\n",tmode); - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = pdu[0]>>4; - curbyte = 0; - curbit = 3; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (pdu[curbyte] >> (curbit-1)) & 0x03; - curbit -= 2; - if (curbit < 0) { - curbit = 7; - curbyte++; - } - } - sched_ctl->dl_cqi[CC_idP] = sched_ctl->aperiodic_wideband_cqi0[CC_idP]; - break; - case CQI_ReportModeAperiodic_rm31: - AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n"); - //subband CQI single PMI (TM4/5/6) - AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm31\n",tmode); - - if ((ri==1) && (cc->p_eNB==2)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t)(p&0x03); - p>>=2; - } - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x03; - } - if ((ri==2) && (cc->p_eNB==2)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=1; - } - sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=1; - } - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x01; - } - if ((ri==1) && (cc->p_eNB==4)) { - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t)(p&0x03); - p>>=2; - } - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x0F; - } - if ((ri>1) && (cc->p_eNB==4)) { // Note : 64 bits for 20 MHz - sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=1; - } - sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4; - for (i=0;i<N;i++) { - sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01); - p>>=2; - } - sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x0F; +void +extract_pusch_csi(module_id_t mod_idP, int CC_idP, int UE_id, + frame_t frameP, sub_frame_t subframeP, + uint8_t * pdu, uint8_t length) +{ + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + int Ntab[6] = { 0, 4, 7, 9, 10, 13 }; + int Ntab_uesel[6] = { 0, 8, 13, 17, 19, 25 }; + int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 }; + int Mtab_uesel[6] = { 0, 1, 3, 5, 6, 6 }; + int v[6]; + int i; + uint64_t p = *(uint64_t *) pdu; + int curbyte, curbit; + CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic; + + AssertFatal(UE_list->UE_template[CC_idP][UE_id]. + physicalConfigDedicated != NULL, + "physicalConfigDedicated is null for UE %d\n", UE_id); + AssertFatal(UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + cqi_ReportConfig != NULL, + "cqi_ReportConfig is null for UE %d\n", UE_id); + AssertFatal((cqi_ReportModeAperiodic = + UE_list-> + UE_template[CC_idP][UE_id].physicalConfigDedicated-> + cqi_ReportConfig->cqi_ReportModeAperiodic) != NULL, + "cqi_ReportModeAperiodic is null for UE %d\n", UE_id); + + int N = Ntab[cc->mib->message.dl_Bandwidth]; + int tmode = get_tmode(mod_idP, CC_idP, UE_id); + int ri = sched_ctl->aperiodic_ri_received[CC_idP]; + int r, diffcqi0 = 0, diffcqi1 = 0, pmi_uesel = 0; + int bw = cc->mib->message.dl_Bandwidth; + int m; + + switch (*cqi_ReportModeAperiodic) { + case CQI_ReportModeAperiodic_rm12: + AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n"); + // wideband multiple PMI (TM4/6), Table 5.2.2.6.1-1 (for TM4/6) + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm12\n", + tmode); + if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213 + if ((ri == 1) && (cc->p_eNB == 2)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x03); + p >>= 2; + } + } + if ((ri == 2) && (cc->p_eNB == 2)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + sched_ctl->aperiodic_wideband_cqi1[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 1; + } + } + if ((ri == 1) && (cc->p_eNB == 4)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x03); + p >>= 4; + } + } + if ((ri == 2) && (cc->p_eNB == 4)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + sched_ctl->aperiodic_wideband_cqi1[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 4; + } + } + } // if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213 + else { + AssertFatal(1 == 0, "support for TM 8-10 to be done\n"); + } + + break; + case CQI_ReportModeAperiodic_rm20: + AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n"); + // UE-selected subband CQI no PMI (TM1/2/3/7) , Table 5.2.2.6.3-1 from 36.213 + AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 + || tmode == 7, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm20\n", + tmode); + + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F); + p >>= 4; + diffcqi0 = (uint8_t) (p & 0x03); + p >>= 2; + r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1)); + reverse_index(Ntab_uesel[bw], Mtab_uesel[bw], r, v); + for (m = 0; m < Mtab_uesel[bw]; m++) + sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0; + break; + case CQI_ReportModeAperiodic_rm22: + AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n"); + // UE-selected subband CQI multiple PMI (TM4/6) Table 5.2.2.6.3-2 from 36.213 + + AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 + || tmode == 10, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm22\n", + tmode); + + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F); + p >>= 4; + diffcqi0 = (uint8_t) (p & 0x03); + p >>= 2; + + if (ri > 1) { + sched_ctl->aperiodic_wideband_cqi1[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + diffcqi1 = (uint8_t) (p & 0x03); + p >>= 2; + } + r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1)); + p >>= Ltab_uesel[bw]; + reverse_index(Ntab_uesel[bw], Mtab_uesel[bw], r, v); + if ((ri == 1) && (cc->p_eNB == 2)) { + pmi_uesel = p & 0x3; + p >>= 2; + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x3; + } else if ((ri == 2) && (cc->p_eNB == 2)) { + pmi_uesel = p & 0x1; + p >>= 1; + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x1; + } else if (cc->p_eNB == 4) { + pmi_uesel = p & 0x0F; + p >>= 4; + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F; + } + for (m = 0; m < Mtab_uesel[bw]; m++) { + sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0; + if (ri > 1) + sched_ctl->aperiodic_subband_diffcqi1[CC_idP][v[m]] = + diffcqi1; + sched_ctl->aperiodic_subband_pmi[CC_idP][v[m]] = pmi_uesel; + } + break; + case CQI_ReportModeAperiodic_rm30: + //subband CQI no PMI (TM1/2/3/7) + AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 + || tmode == 7, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm30\n", + tmode); + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = pdu[0] >> 4; + curbyte = 0; + curbit = 3; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = + (pdu[curbyte] >> (curbit - 1)) & 0x03; + curbit -= 2; + if (curbit < 0) { + curbit = 7; + curbyte++; + } + } + sched_ctl->dl_cqi[CC_idP] = + sched_ctl->aperiodic_wideband_cqi0[CC_idP]; + break; + case CQI_ReportModeAperiodic_rm31: + AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n"); + //subband CQI single PMI (TM4/5/6) + AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 + || tmode == 9 + || tmode == 10, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm31\n", + tmode); + + if ((ri == 1) && (cc->p_eNB == 2)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = + (uint8_t) (p & 0x03); + p >>= 2; + } + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x03; + } + if ((ri == 2) && (cc->p_eNB == 2)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 1; + } + sched_ctl->aperiodic_wideband_cqi1[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 1; + } + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x01; + } + if ((ri == 1) && (cc->p_eNB == 4)) { + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = + (uint8_t) (p & 0x03); + p >>= 2; + } + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F; + } + if ((ri > 1) && (cc->p_eNB == 4)) { // Note : 64 bits for 20 MHz + sched_ctl->aperiodic_wideband_cqi0[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 1; + } + sched_ctl->aperiodic_wideband_cqi1[CC_idP] = + (uint8_t) (p & 0x0F); + p >>= 4; + for (i = 0; i < N; i++) { + sched_ctl->aperiodic_subband_pmi[CC_idP][i] = + (uint8_t) (p & 0x01); + p >>= 2; + } + sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F; + } + + break; + case CQI_ReportModeAperiodic_rm32_v1250: + AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 + || tmode == 9 + || tmode == 10, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm32\n", + tmode); + AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm32 to be done\n"); + break; + case CQI_ReportModeAperiodic_rm10_v1310: + AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 + || tmode == 7, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm10\n", + tmode); + AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm10 to be done\n"); + break; + case CQI_ReportModeAperiodic_rm11_v1310: + AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 + || tmode == 9 + || tmode == 10, + "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm11\n", + tmode); + AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm11 to be done\n"); + break; } - - break; - case CQI_ReportModeAperiodic_rm32_v1250: - AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm32\n",tmode); - AssertFatal(1==0,"CQI_ReportModeAperiodic_rm32 to be done\n"); - break; - case CQI_ReportModeAperiodic_rm10_v1310: - AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm10\n",tmode); - AssertFatal(1==0,"CQI_ReportModeAperiodic_rm10 to be done\n"); - break; - case CQI_ReportModeAperiodic_rm11_v1310: - AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm11\n",tmode); - AssertFatal(1==0,"CQI_ReportModeAperiodic_rm11 to be done\n"); - break; - } } -void cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, rnti_t rntiP, - nfapi_cqi_indication_rel9_t *rel9,uint8_t *pdu, - nfapi_ul_cqi_information_t *ul_cqi_information) +void +cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, rnti_t rntiP, + nfapi_cqi_indication_rel9_t * rel9, uint8_t * pdu, + nfapi_ul_cqi_information_t * ul_cqi_information) { - int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - if (UE_id == -1) { - LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP); - return; - } - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + int UE_id = find_UE_id(mod_idP, rntiP); + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + if (UE_id == -1) { + LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP); + return; + } + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - if (UE_id >= 0) { + if (UE_id >= 0) { - if (ul_cqi_information->channel == 0) { // PUCCH + if (ul_cqi_information->channel == 0) { // PUCCH - // extract pucch csi information before changing RI information - extract_pucch_csi(mod_idP,CC_idP,UE_id,frameP,subframeP,pdu,rel9->length); + // extract pucch csi information before changing RI information + extract_pucch_csi(mod_idP, CC_idP, UE_id, frameP, subframeP, + pdu, rel9->length); - memcpy((void*)sched_ctl->periodic_ri_received, - (void*)rel9->ri, - rel9->number_of_cc_reported); + memcpy((void *) sched_ctl->periodic_ri_received, + (void *) rel9->ri, rel9->number_of_cc_reported); - // SNR for PUCCH2 - sched_ctl->pucch2_snr[CC_idP] = ul_cqi_information->ul_cqi; - } - else { //PUSCH - memcpy((void*)sched_ctl->aperiodic_ri_received, - (void*)rel9->ri, - rel9->number_of_cc_reported); + // SNR for PUCCH2 + sched_ctl->pucch2_snr[CC_idP] = ul_cqi_information->ul_cqi; + } else { //PUSCH + memcpy((void *) sched_ctl->aperiodic_ri_received, + (void *) rel9->ri, rel9->number_of_cc_reported); - extract_pusch_csi(mod_idP,CC_idP,UE_id,frameP,subframeP,pdu,rel9->length); + extract_pusch_csi(mod_idP, CC_idP, UE_id, frameP, subframeP, + pdu, rel9->length); - } + } - // timing advance - sched_ctl->timing_advance = rel9->timing_advance; - sched_ctl->timing_advance_r9 = rel9->timing_advance_r9; - } + // timing advance + sched_ctl->timing_advance = rel9->timing_advance; + sched_ctl->timing_advance_r9 = rel9->timing_advance_r9; + } } -void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, sub_frame_t subframeP, rnti_t rntiP, uint8_t ul_cqi) +void +SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, + sub_frame_t subframeP, rnti_t rntiP, uint8_t ul_cqi) { - T(T_ENB_MAC_SCHEDULING_REQUEST, T_INT(mod_idP), T_INT(cc_idP), T_INT(frameP), T_INT(subframeP), T_INT(rntiP)); + T(T_ENB_MAC_SCHEDULING_REQUEST, T_INT(mod_idP), T_INT(cc_idP), + T_INT(frameP), T_INT(subframeP), T_INT(rntiP)); - int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + int UE_id = find_UE_id(mod_idP, rntiP); + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - if (UE_id != -1) { - if (mac_eNB_get_rrc_status(mod_idP,UE_RNTI(mod_idP,UE_id)) < RRC_CONNECTED) - LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP); + if (UE_id != -1) { + if (mac_eNB_get_rrc_status(mod_idP, UE_RNTI(mod_idP, UE_id)) < + RRC_CONNECTED) + LOG_D(MAC, + "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d\n", + mod_idP, rntiP, frameP, subframeP, UE_id, cc_idP); #if 0 - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - /* for the moment don't use ul_cqi from SR, value is too different from harq */ - sched_ctl->pucch1_snr[cc_idP] = ul_cqi; - sched_ctl->pucch1_cqi_update[cc_idP] = 1; + /* for the moment don't use ul_cqi from SR, value is too different from harq */ + sched_ctl->pucch1_snr[cc_idP] = ul_cqi; + sched_ctl->pucch1_cqi_update[cc_idP] = 1; #endif - UE_list->UE_template[cc_idP][UE_id].ul_SR = 1; - UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION,1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION,0); - } else { - // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); - // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); - LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UEid) on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP); - } + UE_list->UE_template[cc_idP][UE_id].ul_SR = 1; + UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 0); + } else { + // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); + // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); + LOG_D(MAC, + "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UEid) on CC_id %d\n", + mod_idP, rntiP, frameP, subframeP, UE_id, cc_idP); + } } -void UL_failure_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP) +void +UL_failure_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, + rnti_t rntiP, sub_frame_t subframeP) { - int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - - if (UE_id != -1) { - LOG_D(MAC,"[eNB %d][UE %d/%x] Frame %d subframeP %d Signaling UL Failure for UE %d on CC_id %d (timer %d)\n", - mod_idP,UE_id,rntiP,frameP,subframeP, UE_id,cc_idP, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0) - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=1; - } else { - // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); - // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); - LOG_W(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling UL Failure for UE %d (unknown UEid) on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP); - } + int UE_id = find_UE_id(mod_idP, rntiP); + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + + if (UE_id != -1) { + LOG_D(MAC, + "[eNB %d][UE %d/%x] Frame %d subframeP %d Signaling UL Failure for UE %d on CC_id %d (timer %d)\n", + mod_idP, UE_id, rntiP, frameP, subframeP, UE_id, cc_idP, + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0) + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1; + } else { + // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); + // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); + LOG_W(MAC, + "[eNB %d][SR %x] Frame %d subframeP %d Signaling UL Failure for UE %d (unknown UEid) on CC_id %d\n", + mod_idP, rntiP, frameP, subframeP, UE_id, cc_idP); + } } -void harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, nfapi_harq_indication_pdu_t *harq_pdu) +void +harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, + nfapi_harq_indication_pdu_t * harq_pdu) { - rnti_t rnti = harq_pdu->rx_ue_information.rnti; - uint8_t ul_cqi = harq_pdu->ul_cqi_information.ul_cqi; - uint8_t channel = harq_pdu->ul_cqi_information.channel; - int UE_id = find_UE_id(mod_idP, rnti); - if (UE_id == -1) { - LOG_W(MAC, "harq_indication: UE %x not found\n", rnti); - return; - } - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; + rnti_t rnti = harq_pdu->rx_ue_information.rnti; + uint8_t ul_cqi = harq_pdu->ul_cqi_information.ul_cqi; + uint8_t channel = harq_pdu->ul_cqi_information.channel; + int UE_id = find_UE_id(mod_idP, rnti); + if (UE_id == -1) { + LOG_W(MAC, "harq_indication: UE %x not found\n", rnti); + return; + } + UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; // extract HARQ Information - LOG_D(MAC,"Frame %d, subframe %d: Received harq indication (%d) from UE %d/%x, ul_cqi %d\n",frameP,subframeP,channel,UE_id,rnti,ul_cqi); - if (cc->tdd_Config) extract_harq(mod_idP,CC_idP,UE_id,frameP,subframeP,(void*)&harq_pdu->harq_indication_tdd_rel13,channel); - else extract_harq(mod_idP,CC_idP,UE_id,frameP,subframeP,(void*)&harq_pdu->harq_indication_fdd_rel13,channel); - if (channel == 0) { - sched_ctl->pucch1_snr[CC_idP] = ul_cqi; - sched_ctl->pucch1_cqi_update[CC_idP] = 1; - } + LOG_D(MAC, + "Frame %d, subframe %d: Received harq indication (%d) from UE %d/%x, ul_cqi %d\n", + frameP, subframeP, channel, UE_id, rnti, ul_cqi); + if (cc->tdd_Config) + extract_harq(mod_idP, CC_idP, UE_id, frameP, subframeP, + (void *) &harq_pdu->harq_indication_tdd_rel13, + channel); + else + extract_harq(mod_idP, CC_idP, UE_id, frameP, subframeP, + (void *) &harq_pdu->harq_indication_fdd_rel13, + channel); + if (channel == 0) { + sched_ctl->pucch1_snr[CC_idP] = ul_cqi; + sched_ctl->pucch1_cqi_update[CC_idP] = 1; + } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 1fcd07c1d3f889d80827c4da6a0afb4ada035dad..343d391538c27573a5cbbac883f519ee7bf34b99 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -29,6 +29,8 @@ */ +/* indented with: indent -kr eNB_scheduler_RA.c */ + #include "assertions.h" #include "PHY/defs.h" #include "PHY/extern.h" @@ -52,7 +54,7 @@ #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #include "T.h" @@ -61,645 +63,838 @@ #define DEBUG_eNB_SCHEDULER 1 // This table holds the allowable PRB sizes for ULSCH transmissions -uint8_t rb_table[34] = {1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,54,60,64,72,75,80,81,90,96,100}; - -void rx_sdu(const module_id_t enb_mod_idP, - const int CC_idP, - const frame_t frameP, - const sub_frame_t subframeP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const uint16_t timing_advance, - const uint8_t ul_cqi) +uint8_t rb_table[34] = + { 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, + 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96, 100 +}; + +void +rx_sdu(const module_id_t enb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP, + uint8_t * sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, const uint8_t ul_cqi) { - int current_rnti = rntiP; - 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]; - int UE_id = find_UE_id(enb_mod_idP, current_rnti); - int RA_id; - int ii,j; - eNB_MAC_INST *eNB = RC.mac[enb_mod_idP]; - int harq_pid = subframe2harqpid(&eNB->common_channels[CC_idP],frameP,subframeP); - - UE_list_t *UE_list= &eNB->UE_list; - int crnti_rx=0; - int old_buffer_info; - RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[enb_mod_idP]->common_channels[CC_idP].RA_template[0]; - int first_rb = 0; - - start_meas(&eNB->rx_ulsch_sdu); - - if ((UE_id > NUMBER_OF_UE_MAX) || (UE_id == -1) ) - for(ii=0; ii<NB_RB_MAX; ii++) { - rx_lengths[ii] = 0; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,1); - if (opt_enabled == 1) { - trace_pdu(0, sduP,sdu_lenP, 0, 3, current_rnti, frameP, subframeP, 0,0); - LOG_D(OPT,"[eNB %d][ULSCH] Frame %d rnti %x with size %d\n", - enb_mod_idP, frameP, current_rnti, sdu_lenP); - } - - if (UE_id!=-1) { - LOG_D(MAC,"[eNB %d][PUSCH %d] CC_id %d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n",enb_mod_idP,harq_pid,CC_idP, UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid], - current_rnti, UE_id,ul_cqi); - - AssertFatal(UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] < 8, - "round >= 8\n"); - if (sduP!=NULL) { - UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1<<harq_pid)); - /* Update with smoothing: 3/4 of old value and 1/4 of new. - * This is the logic that was done in the function - * lte_est_timing_advance_pusch, maybe it's not necessary? - * maybe it's even not correct at all? - */ - UE_list->UE_sched_ctrl[UE_id].ta_update = - (UE_list->UE_sched_ctrl[UE_id].ta_update * 3 + timing_advance)/4; - UE_list->UE_sched_ctrl[UE_id].pusch_snr[CC_idP] = ul_cqi; - UE_list->UE_sched_ctrl[UE_id].ul_consecutive_errors = 0; - first_rb = UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid]; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) { - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=0; - mac_eNB_rrc_ul_in_sync(enb_mod_idP,CC_idP,frameP,subframeP,UE_RNTI(enb_mod_idP,UE_id)); - } + int current_rnti = rntiP; + 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]; + int UE_id = find_UE_id(enb_mod_idP, current_rnti); + int RA_id; + int ii, j; + eNB_MAC_INST *mac = RC.mac[enb_mod_idP]; + int harq_pid = + subframe2harqpid(&mac->common_channels[CC_idP], frameP, subframeP); + + UE_list_t *UE_list = &mac->UE_list; + int crnti_rx = 0; + int old_buffer_info; + RA_t *ra = + (RA_t *) & RC.mac[enb_mod_idP]->common_channels[CC_idP].ra[0]; + int first_rb = 0; + + start_meas(&mac->rx_ulsch_sdu); + + if ((UE_id > NUMBER_OF_UE_MAX) || (UE_id == -1)) + for (ii = 0; ii < NB_RB_MAX; ii++) { + rx_lengths[ii] = 0; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU, 1); + if (opt_enabled == 1) { + trace_pdu(0, sduP, sdu_lenP, 0, 3, current_rnti, frameP, subframeP, + 0, 0); + LOG_D(OPT, "[eNB %d][ULSCH] Frame %d rnti %x with size %d\n", + enb_mod_idP, frameP, current_rnti, sdu_lenP); } - else { // we've got an error - LOG_D(MAC,"[eNB %d][PUSCH %d] CC_id %d ULSCH in error in round %d, ul_cqi %d\n",enb_mod_idP,harq_pid,CC_idP, - UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid],ul_cqi); - - // AssertFatal(1==0,"ulsch in error\n"); - if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] == 3) { - UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1<<harq_pid)); - UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid]=0; - if (UE_list->UE_sched_ctrl[UE_id].ul_consecutive_errors++ == 10) - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1; - } - else UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid]++; - return; + if (UE_id != -1) { + LOG_D(MAC, + "[eNB %d][PUSCH %d] CC_id %d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n", + enb_mod_idP, harq_pid, CC_idP, + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid], + current_rnti, UE_id, ul_cqi); + + AssertFatal(UE_list->UE_sched_ctrl[UE_id]. + round_UL[CC_idP][harq_pid] < 8, "round >= 8\n"); + if (sduP != NULL) { + UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0; + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= + (~(1 << harq_pid)); + /* Update with smoothing: 3/4 of old value and 1/4 of new. + * This is the logic that was done in the function + * lte_est_timing_advance_pusch, maybe it's not necessary? + * maybe it's even not correct at all? + */ + UE_list->UE_sched_ctrl[UE_id].ta_update = + (UE_list->UE_sched_ctrl[UE_id].ta_update * 3 + + timing_advance) / 4; + UE_list->UE_sched_ctrl[UE_id].pusch_snr[CC_idP] = ul_cqi; + UE_list->UE_sched_ctrl[UE_id].ul_consecutive_errors = 0; + first_rb = + UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid]; + + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) { + UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0; + mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP, + subframeP, UE_RNTI(enb_mod_idP, + UE_id)); + } + } else { // we've got an error + LOG_D(MAC, + "[eNB %d][PUSCH %d] CC_id %d ULSCH in error in round %d, ul_cqi %d\n", + enb_mod_idP, harq_pid, CC_idP, + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid], + ul_cqi); + + // AssertFatal(1==0,"ulsch in error\n"); + if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] == + 3) { + UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= + (~(1 << harq_pid)); + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] = + 0; + if (UE_list->UE_sched_ctrl[UE_id]. + ul_consecutive_errors++ == 10) + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1; + } else + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid]++; + return; + + } + } else if ((RA_id = find_RA_id(enb_mod_idP, CC_idP, current_rnti)) != -1) { // Check if this is an RA process for the rnti + AssertFatal(mac->common_channels[CC_idP]. + radioResourceConfigCommon->rach_ConfigCommon. + maxHARQ_Msg3Tx > 1, + "maxHARQ %d should be greater than 1\n", + (int) mac->common_channels[CC_idP]. + radioResourceConfigCommon->rach_ConfigCommon. + maxHARQ_Msg3Tx); + + LOG_D(MAC, + "[eNB %d][PUSCH %d] CC_id %d Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n", + enb_mod_idP, harq_pid, CC_idP, ra[RA_id].msg3_round, + current_rnti, RA_id, ul_cqi); + + first_rb = ra->msg3_first_rb; + + if (sduP == NULL) { // we've got an error on Msg3 + LOG_D(MAC, + "[eNB %d] CC_id %d, RA %d ULSCH in error in round %d/%d\n", + enb_mod_idP, CC_idP, RA_id, + ra[RA_id].msg3_round, + (int) mac->common_channels[CC_idP]. + radioResourceConfigCommon->rach_ConfigCommon. + maxHARQ_Msg3Tx); + if (ra[RA_id].msg3_round == + mac->common_channels[CC_idP].radioResourceConfigCommon-> + rach_ConfigCommon.maxHARQ_Msg3Tx - 1) { + cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti); + } + + else { + first_rb = + UE_list->UE_template[CC_idP][UE_id]. + first_rb_ul[harq_pid]; + ra[RA_id].msg3_round++; + // prepare handling of retransmission + ra[RA_id].Msg3_frame += + ((ra[RA_id].Msg3_subframe > 1) ? 1 : 0); + ra[RA_id].Msg3_subframe = + (ra[RA_id].Msg3_subframe + 8) % 10; + add_msg3(enb_mod_idP, CC_idP, &ra[RA_id], frameP, + subframeP); + } + return; + } + } else { + LOG_W(MAC, + "Cannot find UE or RA corresponding to ULSCH rnti %x, dropping it\n", + current_rnti); + return; } - } - else if ((RA_id = find_RA_id(enb_mod_idP,CC_idP,current_rnti))!=-1) { // Check if this is an RA process for the rnti - AssertFatal(eNB->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx>1, - "maxHARQ %d should be greater than 1\n", - (int)eNB->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx); - - LOG_D(MAC,"[eNB %d][PUSCH %d] CC_id %d Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n",enb_mod_idP,harq_pid,CC_idP, - RA_template[RA_id].msg3_round, - current_rnti,RA_id,ul_cqi); - - first_rb = RA_template->msg3_first_rb; - - if (sduP==NULL) { // we've got an error on Msg3 - LOG_D(MAC,"[eNB %d] CC_id %d, RA %d ULSCH in error in round %d/%d\n",enb_mod_idP,CC_idP,RA_id, - RA_template[RA_id].msg3_round, - (int)eNB->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx); - if (RA_template[RA_id].msg3_round == eNB->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx-1) { - cancel_ra_proc(enb_mod_idP,CC_idP,frameP,current_rnti); - } - - else { - first_rb = UE_list->UE_template[CC_idP][UE_id].first_rb_ul[harq_pid]; - RA_template[RA_id].msg3_round++; - // prepare handling of retransmission - RA_template[RA_id].Msg3_frame += ((RA_template[RA_id].Msg3_subframe>1) ? 1 : 0); - RA_template[RA_id].Msg3_subframe = (RA_template[RA_id].Msg3_subframe+8)%10; - add_msg3(enb_mod_idP,CC_idP, &RA_template[RA_id],frameP,subframeP); - } - return; - } - } - else { - LOG_W(MAC,"Cannot find UE or RA corresponding to ULSCH rnti %x, dropping it\n", current_rnti); - return; - } - payload_ptr = parse_ulsch_header(sduP,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_lenP); - - T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu)); - T(T_ENB_MAC_UE_UL_PDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu), T_BUFFER(sduP, sdu_lenP)); - - eNB->eNB_stats[CC_idP].ulsch_bytes_rx=sdu_lenP; - eNB->eNB_stats[CC_idP].total_ulsch_bytes_rx+=sdu_lenP; - eNB->eNB_stats[CC_idP].total_ulsch_pdus_rx+=1; - - UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] = 0; - - // control element - for (i=0; i<num_ce; i++) { - - T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), - T_INT(rx_ces[i])); - - switch (rx_ces[i]) { // implement and process BSR + CRNTI + - case POWER_HEADROOM: - if (UE_id != -1) { - UE_list->UE_template[CC_idP][UE_id].phr_info = (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET; - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n", - enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].phr_info); - UE_list->UE_template[CC_idP][UE_id].phr_info_configured=1; - UE_list->UE_sched_ctrl[UE_id].phr_received = 1; - } - payload_ptr+=sizeof(POWER_HEADROOM_CMD); - break; - - case CRNTI: { - int old_rnti = (((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]; - int old_UE_id = find_UE_id(enb_mod_idP, old_rnti); - LOG_D(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n", - enb_mod_idP, frameP, subframeP, CC_idP, rx_ces[i], i, num_ce, old_rnti, old_UE_id); - if (old_UE_id != -1) { - /* TODO: if the UE did random access (followed by a MAC uplink with - * CRNTI) because none of its scheduling request was granted, then - * according to 36.321 5.4.4 the UE's MAC will notify RRC to release - * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply - * default configuration for CQI reporting and scheduling requests, - * which basically means that the CQI requests won't work anymore and - * that the UE won't do any scheduling request anymore as long as the - * eNB doesn't reconfigure the UE. - * We have to take care of this. As the code is, nothing is done and - * the UE state in the eNB is wrong. - */ - UE_id = old_UE_id; - UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) { - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0; - mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP, subframeP, old_rnti); - } - /* receiving CRNTI means that the current rnti has to go away */ - cancel_ra_proc(enb_mod_idP,CC_idP,frameP,current_rnti); - current_rnti = old_rnti; - } - crnti_rx=1; - payload_ptr+=2; - break; + payload_ptr = + parse_ulsch_header(sduP, &num_ce, &num_sdu, rx_ces, rx_lcids, + rx_lengths, sdu_lenP); + + T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP), + T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), + T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu)); + T(T_ENB_MAC_UE_UL_PDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), + T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), + T_INT(harq_pid), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu), + T_BUFFER(sduP, sdu_lenP)); + + mac->eNB_stats[CC_idP].ulsch_bytes_rx = sdu_lenP; + mac->eNB_stats[CC_idP].total_ulsch_bytes_rx += sdu_lenP; + mac->eNB_stats[CC_idP].total_ulsch_pdus_rx += 1; + + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_idP][harq_pid] = 0; + + // control element + for (i = 0; i < num_ce; i++) { + + T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP), + T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), + T_INT(rx_ces[i])); + + switch (rx_ces[i]) { // implement and process BSR + CRNTI + + case POWER_HEADROOM: + if (UE_id != -1) { + UE_list->UE_template[CC_idP][UE_id].phr_info = + (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET; + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n", + enb_mod_idP, CC_idP, rx_ces[i], + UE_list->UE_template[CC_idP][UE_id].phr_info); + UE_list->UE_template[CC_idP][UE_id].phr_info_configured = + 1; + UE_list->UE_sched_ctrl[UE_id].phr_received = 1; + } + payload_ptr += sizeof(POWER_HEADROOM_CMD); + break; + + case CRNTI: + { + int old_rnti = + (((uint16_t) payload_ptr[0]) << 8) + payload_ptr[1]; + int old_UE_id = find_UE_id(enb_mod_idP, old_rnti); + LOG_D(MAC, + "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n", + enb_mod_idP, frameP, subframeP, CC_idP, rx_ces[i], i, + num_ce, old_rnti, old_UE_id); + if (old_UE_id != -1) { + /* TODO: if the UE did random access (followed by a MAC uplink with + * CRNTI) because none of its scheduling request was granted, then + * according to 36.321 5.4.4 the UE's MAC will notify RRC to release + * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply + * default configuration for CQI reporting and scheduling requests, + * which basically means that the CQI requests won't work anymore and + * that the UE won't do any scheduling request anymore as long as the + * eNB doesn't reconfigure the UE. + * We have to take care of this. As the code is, nothing is done and + * the UE state in the eNB is wrong. + */ + UE_id = old_UE_id; + UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0; + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) { + UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0; + mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP, + subframeP, old_rnti); + } + /* receiving CRNTI means that the current rnti has to go away */ + cancel_ra_proc(enb_mod_idP, CC_idP, frameP, + current_rnti); + current_rnti = old_rnti; + } + crnti_rx = 1; + payload_ptr += 2; + break; + } + + case TRUNCATED_BSR: + case SHORT_BSR: + { + uint8_t lcgid; + lcgid = (payload_ptr[0] >> 6); + + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", + enb_mod_idP, CC_idP, rx_ces[i], lcgid, + payload_ptr[0] & 0x3f); + + if (crnti_rx == 1) + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", + enb_mod_idP, CC_idP, rx_ces[i], lcgid, + payload_ptr[0] & 0x3f); + if (UE_id != -1) { + + UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = + (payload_ptr[0] & 0x3f); + + // update buffer info + + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[lcgid] = + BSR_TABLE[UE_list->UE_template[CC_idP][UE_id]. + bsr_info[lcgid]]; + + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[lcgid]; + + RC.eNB[enb_mod_idP][CC_idP]-> + pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] + = (payload_ptr[0] & 0x3f); + if (UE_id == UE_list->head) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME + (VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, + RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr + [UE_id][(frameP * 10) + subframeP]); + if (UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[lcgid] + == 0) { + UE_list->UE_template[CC_idP] + [UE_id].ul_buffer_creation_time[lcgid] = + frameP; + } + if (mac_eNB_get_rrc_status + (enb_mod_idP, + UE_RNTI(enb_mod_idP, UE_id)) < RRC_CONNECTED) + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d : ul_total_buffer = %d (lcg increment %d)\n", + enb_mod_idP, CC_idP, rx_ces[i], + UE_list->UE_template[CC_idP][UE_id]. + ul_total_buffer, + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[lcgid]); + } else { + + } + payload_ptr += 1; //sizeof(SHORT_BSR); // fixme + } + break; + + case LONG_BSR: + if (UE_id != -1) { + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] = + ((payload_ptr[0] & 0xFC) >> 2); + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] = + ((payload_ptr[0] & 0x03) << 4) | + ((payload_ptr[1] & 0xF0) >> 4); + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] = + ((payload_ptr[1] & 0x0F) << 2) | + ((payload_ptr[2] & 0xC0) >> 6); + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] = + (payload_ptr[2] & 0x3F); + + // update buffer info + old_buffer_info = + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID0]; + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID0] = + BSR_TABLE[UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID0]]; + + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer += + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID0]; + if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= + old_buffer_info) + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= + old_buffer_info; + else + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = + 0; + + old_buffer_info = + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID1]; + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID1] = + BSR_TABLE[UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID1]]; + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer += + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID1]; + if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= + old_buffer_info) + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= + old_buffer_info; + else + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = + 0; + + old_buffer_info = + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID2]; + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID2] = + BSR_TABLE[UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID2]]; + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer += + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID2]; + if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= + old_buffer_info) + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= + old_buffer_info; + else + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = + 0; + + old_buffer_info = + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID3]; + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID3] = + BSR_TABLE[UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID3]]; + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer += + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[LCGID3]; + if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= + old_buffer_info) + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= + old_buffer_info; + else + UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = + 0; + + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " + "%u LCGID2 = %u LCGID3 = %u\n", enb_mod_idP, CC_idP, + rx_ces[i], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2], + UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID3]); + if (crnti_rx == 1) + LOG_D(MAC, + "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " + "%u LCGID2 = %u LCGID3 = %u\n", enb_mod_idP, + CC_idP, rx_ces[i], + UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID0], + UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID1], + UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID2], + UE_list->UE_template[CC_idP][UE_id]. + bsr_info[LCGID3]); + + if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] == + 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID0] = 0; + } else if (UE_list->UE_template[CC_idP] + [UE_id].ul_buffer_creation_time[LCGID0] == 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID0] = frameP; + } + + if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] == + 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID1] = 0; + } else if (UE_list->UE_template[CC_idP] + [UE_id].ul_buffer_creation_time[LCGID1] == 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID1] = frameP; + } + + if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] == + 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID2] = 0; + } else if (UE_list->UE_template[CC_idP] + [UE_id].ul_buffer_creation_time[LCGID2] == 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID2] = frameP; + } + + if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] == + 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID3] = 0; + } else if (UE_list->UE_template[CC_idP] + [UE_id].ul_buffer_creation_time[LCGID3] == 0) { + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_creation_time[LCGID3] = frameP; + + } + } + + payload_ptr += 3; ////sizeof(LONG_BSR); + break; + + default: + LOG_E(MAC, + "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n", + enb_mod_idP, CC_idP, rx_ces[i]); + break; + } } - case TRUNCATED_BSR: - case SHORT_BSR: { - uint8_t lcgid; - lcgid = (payload_ptr[0] >> 6); - - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", - enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f); - - if (crnti_rx==1) - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", - enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f); - if (UE_id != -1) { - - UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f); - - // update buffer info - - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid]]; - - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]; - - RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP] = (payload_ptr[0] & 0x3f); - if (UE_id == UE_list->head) - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP]); - if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] == 0 ) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid]=frameP; - } - if (mac_eNB_get_rrc_status(enb_mod_idP,UE_RNTI(enb_mod_idP,UE_id)) < RRC_CONNECTED) - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : ul_total_buffer = %d (lcg increment %d)\n", - enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].ul_total_buffer, - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]); - } - else { - - } - payload_ptr += 1;//sizeof(SHORT_BSR); // fixme - } - break; - - case LONG_BSR: - if (UE_id != -1) { - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] = ((payload_ptr[0] & 0xFC) >> 2); - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] = - ((payload_ptr[0] & 0x03) << 4) | ((payload_ptr[1] & 0xF0) >> 4); - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] = - ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6); - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] = (payload_ptr[2] & 0x3F); - - // update buffer info - old_buffer_info = UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0]; - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0]]; - - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer+= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0]; - if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= old_buffer_info) - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= old_buffer_info; - else - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = 0; - - old_buffer_info = UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1]; - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1]]; - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer+= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1]; - if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= old_buffer_info) - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= old_buffer_info; - else - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = 0; - - old_buffer_info = UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2]; - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2]]; - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer+= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2]; - if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= old_buffer_info) - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= old_buffer_info; - else - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = 0; - - old_buffer_info = UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3]; - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]]; - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer+= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3]; - if (UE_list->UE_template[CC_idP][UE_id].ul_total_buffer >= old_buffer_info) - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer -= old_buffer_info; - else - UE_list->UE_template[CC_idP][UE_id].ul_total_buffer = 0; - - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " - "%u LCGID2 = %u LCGID3 = %u\n", - enb_mod_idP, CC_idP, - rx_ces[i], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]); - if (crnti_rx==1) - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " - "%u LCGID2 = %u LCGID3 = %u\n", - enb_mod_idP, CC_idP, - rx_ces[i], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2], - UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]); - - if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] == 0 ) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0]=0; - } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0] == 0) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0]=frameP; - } - - if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] == 0 ) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1]=0; - } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1] == 0) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1]=frameP; - } - - if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] == 0 ) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2]=0; - } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2] == 0) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2]=frameP; - } - - if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] == 0 ) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3]= 0; - } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3] == 0) { - UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3]=frameP; - - } - } - - payload_ptr += 3;////sizeof(LONG_BSR); - break; - - default: - LOG_E(MAC, "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n", enb_mod_idP, CC_idP, rx_ces[i]); - break; - } - } - - for (i=0; i<num_sdu; i++) { - LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]); - - T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), - T_INT(rx_lcids[i]), T_INT(rx_lengths[i])); - T(T_ENB_MAC_UE_UL_SDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), - T_INT(rx_lcids[i]), T_INT(rx_lengths[i]), T_BUFFER(payload_ptr, rx_lengths[i])); - - switch (rx_lcids[i]) { - case CCCH : - if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) { - LOG_E(MAC, "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n", - enb_mod_idP, CC_idP, frameP, rx_lengths[i], CCCH_PAYLOAD_SIZE_MAX,sdu_lenP); - break; - } - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n", - enb_mod_idP,CC_idP,frameP, - payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], current_rnti); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,0); - for (ii=0; ii<NB_RA_PROC_MAX; ii++) { - RA_TEMPLATE *RA_template = &eNB->common_channels[CC_idP].RA_template[ii]; - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), active %d\n", - enb_mod_idP, CC_idP, ii, - RA_template->rnti, current_rnti, - RA_template->RA_active); - - if ((RA_template->rnti==current_rnti) && - (RA_template->RA_active==TRUE)) { - - //payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len); - - if (UE_id < 0) { - memcpy(&RA_template->cont_res_id[0],payload_ptr,6); - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %ld\n", - enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP); - - if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pid - #ifdef Rel14 - ,eNB->common_channels[CC_idP].RA_template[ii].rach_resource_type - #endif - )) == -1 ) { - AssertFatal(1==0,"[MAC][eNB] Max user count reached\n"); - // kill RA procedure - } else - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n", - enb_mod_idP,CC_idP,frameP,RA_template->rnti,UE_id); - } else { - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n", - enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP); - // kill RA procedure - } - - mac_rrc_data_ind( - enb_mod_idP, - CC_idP, - frameP,subframeP, - current_rnti, - CCCH, - (uint8_t*)payload_ptr, - rx_lengths[i], - ENB_FLAG_YES, - enb_mod_idP, - 0 - ); - - - if (num_ce >0) { // handle msg3 which is not RRCConnectionRequest - // process_ra_message(msg3,num_ce,rx_lcids,rx_ces); - } - - // prepare transmission of Msg4 - RA_template->generate_Msg4 = 1; - RA_template->wait_ack_Msg4 = 0; - - - - // Program Msg4 PDCCH+DLSCH/MPDCCH transmission 4 subframes from now, // Check if this is ok for BL/CE, or if the rule is different - RA_template->Msg4_frame = frameP + ((subframeP>5) ? 1 : 0); - RA_template->Msg4_subframe = (subframeP+4)%10; - - } // if process is active - } // loop on RA processes - - break ; - - case DCCH : - case DCCH1 : - // if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){ + for (i = 0; i < num_sdu; i++) { + LOG_D(MAC, "SDU Number %d MAC Subheader SDU_LCID %d, length %d\n", + i, rx_lcids[i], rx_lengths[i]); + + T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP), + T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), + T_INT(rx_lcids[i]), T_INT(rx_lengths[i])); + T(T_ENB_MAC_UE_UL_SDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), + T_INT(current_rnti), T_INT(frameP), T_INT(subframeP), + T_INT(rx_lcids[i]), T_INT(rx_lengths[i]), T_BUFFER(payload_ptr, + rx_lengths + [i])); + + switch (rx_lcids[i]) { + case CCCH: + if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) { + LOG_E(MAC, + "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n", + enb_mod_idP, CC_idP, frameP, rx_lengths[i], + CCCH_PAYLOAD_SIZE_MAX, sdu_lenP); + break; + } + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n", + enb_mod_idP, CC_idP, frameP, payload_ptr[0], + payload_ptr[1], payload_ptr[2], payload_ptr[3], + payload_ptr[4], payload_ptr[5], current_rnti); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC, 1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC, 0); + for (ii = 0; ii < NB_RA_PROC_MAX; ii++) { + RA_t *ra = &mac->common_channels[CC_idP].ra[ii]; + + LOG_D(MAC, + "[mac %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), state %d\n", + enb_mod_idP, CC_idP, ii, ra->rnti, + current_rnti, ra->state); + + if ((ra->rnti == current_rnti) && (ra->state != IDLE)) { + + //payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len); + + if (UE_id < 0) { + memcpy(&ra->cont_res_id[0], payload_ptr, 6); + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %ld\n", + enb_mod_idP, CC_idP, frameP, rx_lengths[i], + payload_ptr - sduP); + + if ((UE_id = + add_new_ue(enb_mod_idP, CC_idP, + mac->common_channels[CC_idP]. + ra[ii].rnti, harq_pid +#ifdef Rel14 + , + mac->common_channels[CC_idP]. + ra[ii].rach_resource_type +#endif + )) == -1) { + AssertFatal(1 == 0, + "[MAC][eNB] Max user count reached\n"); + // kill RA procedure + } else + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n", + enb_mod_idP, CC_idP, frameP, ra->rnti, + UE_id); + } else { + LOG_D(MAC, + "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n", + enb_mod_idP, CC_idP, frameP, UE_id, + rx_lengths[i], payload_ptr - sduP); + // kill RA procedure + } + + mac_rrc_data_ind(enb_mod_idP, + CC_idP, + frameP, subframeP, + current_rnti, + CCCH, + (uint8_t *) payload_ptr, + rx_lengths[i], + ENB_FLAG_YES, enb_mod_idP, 0); + + + if (num_ce > 0) { // handle msg3 which is not RRCConnectionRequest + // process_ra_message(msg3,num_ce,rx_lcids,rx_ces); + } + // prepare transmission of Msg4 + ra->state = MSG4; + + + + // Program Msg4 PDCCH+DLSCH/MPDCCH transmission 4 subframes from now, // Check if this is ok for BL/CE, or if the rule is different + ra->Msg4_frame = frameP + ((subframeP > 5) ? 1 : 0); + ra->Msg4_subframe = (subframeP + 4) % 10; + + } // if process is active + } // loop on RA processes + + break; + + case DCCH: + case DCCH1: + // if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){ #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP)); - for (j=0; j<32; j++) { - LOG_T(MAC,"%x ",payload_ptr[j]); - } - LOG_T(MAC,"\n"); + LOG_T(MAC, "offset: %d\n", + (unsigned char) ((unsigned char *) payload_ptr - sduP)); + for (j = 0; j < 32; j++) { + LOG_T(MAC, "%x ", payload_ptr[j]); + } + LOG_T(MAC, "\n"); #endif - if (UE_id != -1) { - // adjust buffer occupancy of the correponding logical channel group - if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i]) - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i]; - else - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0; - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n", - enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]); - - mac_rlc_data_ind( - enb_mod_idP, - current_rnti, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; - - - } /* UE_id != -1 */ - - - // } - break; - - // all the DRBS - case DTCH: - default : + if (UE_id != -1) { + // adjust buffer occupancy of the correponding logical channel group + if (UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]] >= + rx_lengths[i]) + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]] -= + rx_lengths[i]; + else + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]] = 0; + + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n", + enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id, + rx_lcids[i]); + + mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); //(unsigned int*)crc_status); + UE_list->eNB_UE_stats[CC_idP][UE_id]. + num_pdu_rx[rx_lcids[i]] += 1; + UE_list->eNB_UE_stats[CC_idP][UE_id]. + num_bytes_rx[rx_lcids[i]] + += rx_lengths[i]; + + + } + + /* UE_id != -1 */ + // } + break; + + // all the DRBS + case DTCH: + default: #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP)); - for (j=0; j<32; j++) { - LOG_T(MAC,"%x ",payload_ptr[j]); - } - LOG_T(MAC,"\n"); + LOG_T(MAC, "offset: %d\n", + (unsigned char) ((unsigned char *) payload_ptr - sduP)); + for (j = 0; j < 32; j++) { + LOG_T(MAC, "%x ", payload_ptr[j]); + } + LOG_T(MAC, "\n"); #endif - if (rx_lcids[i] < NB_RB_MAX ) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n", - enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]); - - if (UE_id != -1) { - // adjust buffer occupancy of the correponding logical channel group - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d, removing from LCGID %ld, %d\n", - enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id,rx_lcids[i], - UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]], - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]]); - - if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i]) - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i]; - else - UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0; - if ((rx_lengths[i] <SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0) ) { // MAX SIZE OF transport block - mac_rlc_data_ind( - enb_mod_idP, - current_rnti, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); - - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; - } - else { /* rx_length[i] */ - UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1; - LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", - enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id); - } - } - else {/*(UE_id != -1*/ - LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", - enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id); - } - } - - break; + if (rx_lcids[i] < NB_RB_MAX) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n", + enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id, + rx_lcids[i]); + + if (UE_id != -1) { + // adjust buffer occupancy of the correponding logical channel group + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d, removing from LCGID %ld, %d\n", + enb_mod_idP, CC_idP, frameP, rx_lengths[i], + UE_id, rx_lcids[i], + UE_list->UE_template[CC_idP][UE_id]. + lcgidmap[rx_lcids[i]], + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]]); + + if (UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]] + >= rx_lengths[i]) + UE_list->UE_template[CC_idP][UE_id]. + ul_buffer_info[UE_list->UE_template[CC_idP] + [UE_id].lcgidmap[rx_lcids[i]]] + -= rx_lengths[i]; + else + UE_list->UE_template[CC_idP][UE_id].ul_buffer_info + [UE_list->UE_template[CC_idP][UE_id].lcgidmap + [rx_lcids[i]]] = 0; + if ((rx_lengths[i] < SCH_PAYLOAD_SIZE_MAX) + && (rx_lengths[i] > 0)) { // MAX SIZE OF transport block + mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); //(unsigned int*)crc_status); + + UE_list->eNB_UE_stats[CC_idP][UE_id]. + num_pdu_rx[rx_lcids[i]] += 1; + UE_list->eNB_UE_stats[CC_idP][UE_id]. + num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + } else { /* rx_length[i] */ + UE_list->eNB_UE_stats[CC_idP][UE_id]. + num_errors_rx += 1; + LOG_E(MAC, + "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", + enb_mod_idP, CC_idP, frameP, rx_lcids[i], + UE_id); + } + } else { /*(UE_id != -1 */ + LOG_E(MAC, + "[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", + enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id); + } + } + + break; + } + + payload_ptr += rx_lengths[i]; } - payload_ptr+=rx_lengths[i]; - } - - // Program ACK for PHICH - LOG_D(MAC,"Programming PHICH ACK for rnti %x harq_pid %d (first_rb %d)\n",current_rnti,harq_pid,first_rb); - nfapi_hi_dci0_request_body_t *hi_dci0_req = &eNB->HI_DCI0_req[CC_idP].hi_dci0_request_body; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi]; - memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_hi_pdu); - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 1; - hi_dci0_req->number_of_hi++; - - /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */ - if ((num_sdu == 0) && (num_ce==0)) { - if (UE_id != -1) - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx+=1; - /* - if (msg3_flagP != NULL) { - if( *msg3_flagP == 1 ) { - LOG_N(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP); - *msg3_flagP=0; - } - }*/ - } else { - if (UE_id != -1) { - UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx=sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx+=sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx+=1; + // Program ACK for PHICH + LOG_D(MAC, + "Programming PHICH ACK for rnti %x harq_pid %d (first_rb %d)\n", + current_rnti, harq_pid, first_rb); + nfapi_hi_dci0_request_body_t *hi_dci0_req = + &mac->HI_DCI0_req[CC_idP].hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = + &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci + + hi_dci0_req->number_of_hi]; + memset((void *) hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu); + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 1; + hi_dci0_req->number_of_hi++; + + /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */ + if ((num_sdu == 0) && (num_ce == 0)) { + if (UE_id != -1) + UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1; + /* + if (msg3_flagP != NULL) { + if( *msg3_flagP == 1 ) { + LOG_N(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP); + *msg3_flagP=0; + } + } */ + } else { + if (UE_id != -1) { + UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx = sdu_lenP; + UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += + sdu_lenP; + UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx += 1; + } } - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,0); - stop_meas(&eNB->rx_ulsch_sdu); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU, 0); + stop_meas(&mac->rx_ulsch_sdu); } uint32_t bytes_to_bsr_index(int32_t nbytes) { - uint32_t i=0; + uint32_t i = 0; - if (nbytes<0) { - return(0); - } + if (nbytes < 0) { + return (0); + } - while ((i<BSR_TABLE_SIZE)&& - (BSR_TABLE[i]<=nbytes)) { - i++; - } + while ((i < BSR_TABLE_SIZE) && (BSR_TABLE[i] <= nbytes)) { + i++; + } - return(i-1); + return (i - 1); } -void add_ue_ulsch_info(module_id_t module_idP, int CC_id, int UE_id, sub_frame_t subframeP, UE_ULSCH_STATUS status) +void +add_ue_ulsch_info(module_id_t module_idP, int CC_id, int UE_id, + sub_frame_t subframeP, UE_ULSCH_STATUS status) { - eNB_ulsch_info[module_idP][CC_id][UE_id].rnti = UE_RNTI(module_idP,UE_id); - eNB_ulsch_info[module_idP][CC_id][UE_id].subframe = subframeP; - eNB_ulsch_info[module_idP][CC_id][UE_id].status = status; + eNB_ulsch_info[module_idP][CC_id][UE_id].rnti = + UE_RNTI(module_idP, UE_id); + eNB_ulsch_info[module_idP][CC_id][UE_id].subframe = subframeP; + eNB_ulsch_info[module_idP][CC_id][UE_id].status = status; - eNB_ulsch_info[module_idP][CC_id][UE_id].serving_num++; + eNB_ulsch_info[module_idP][CC_id][UE_id].serving_num++; } 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 *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 %ld)\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+=3; - } else if (lcid==CRNTI) { - ce_len+=2; - } else if ((lcid==POWER_HEADROOM) || (lcid==TRUNCATED_BSR)|| (lcid== SHORT_BSR)) { - ce_len++; - } else { - LOG_E(MAC,"unknown CE %d \n", lcid); - AssertFatal(1==0,"unknown CE"); - } - } + 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 %ld)\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 += 3; + } else if (lcid == CRNTI) { + ce_len += 2; + } else if ((lcid == POWER_HEADROOM) + || (lcid == TRUNCATED_BSR) + || (lcid == SHORT_BSR)) { + ce_len++; + } else { + LOG_E(MAC, "unknown CE %d \n", lcid); + AssertFatal(1 == 0, "unknown CE"); + } + } + } } - } - *num_ce = num_ces; - *num_sdu = num_sdus; + *num_ce = num_ces; + *num_sdu = num_sdus; - return(mac_header_ptr); + return (mac_header_ptr); } /* This function is called by PHY layer when it schedules some @@ -707,538 +902,629 @@ unsigned char *parse_ulsch_header(unsigned char *mac_header, * The MAC scheduler has to skip the RBs used by this message 3 * (done below in schedule_ulsch). */ -void set_msg3_subframe(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - int rnti, - int Msg3_frame, - int Msg3_subframe) +void +set_msg3_subframe(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, int rnti, int Msg3_frame, + int Msg3_subframe) { - eNB_MAC_INST *eNB=RC.mac[Mod_id]; - int i; - for (i=0; i<NB_RA_PROC_MAX; i++) { - if (eNB->common_channels[CC_id].RA_template[i].RA_active == TRUE && - eNB->common_channels[CC_id].RA_template[i].rnti == rnti) { - eNB->common_channels[CC_id].RA_template[i].Msg3_subframe = Msg3_subframe; - break; + eNB_MAC_INST *mac = RC.mac[Mod_id]; + int i; + for (i = 0; i < NB_RA_PROC_MAX; i++) { + if (mac->common_channels[CC_id].ra[i].state != IDLE && + mac->common_channels[CC_id].ra[i].rnti == rnti) { + mac->common_channels[CC_id].ra[i].Msg3_subframe = + Msg3_subframe; + break; + } } - } } -void schedule_ulsch(module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP) +void +schedule_ulsch(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP) { - uint16_t first_rb[MAX_NUM_CCs],i; - int CC_id; - eNB_MAC_INST *eNB=RC.mac[module_idP]; - COMMON_channels_t *cc; - - start_meas(&eNB->schedule_ulsch); - - int sched_subframe = (subframeP+4)%10; - - cc = &eNB->common_channels[0]; - int tdd_sfa; - // for TDD: check subframes where we have to act and return if nothing should be done now - if (cc->tdd_Config) { - tdd_sfa = cc->tdd_Config->subframeAssignment; - switch (subframeP) { - case 0: - if ((tdd_sfa == 0)|| - (tdd_sfa == 3)|| - (tdd_sfa == 6)) sched_subframe = 4; - else return; - break; - case 1: - if ((tdd_sfa==0)|| - (tdd_sfa==1)) sched_subframe = 7; - else if (tdd_sfa==6) sched_subframe = 8; - break; - default: - return; - - case 2: // Don't schedule UL in subframe 2 for TDD - return; - case 3: - if (tdd_sfa==2) sched_subframe = 7; - else return; - break; - case 4: - if (tdd_sfa==1) sched_subframe = 8; - else return; - break; - case 5: - if (tdd_sfa==0) sched_subframe = 9; - else if (tdd_sfa==6) sched_subframe = 3; - else return; - break; - case 6: - if (tdd_sfa==1) sched_subframe = 2; - else if (tdd_sfa==6) sched_subframe = 3; - else return; - break; - case 7: - return; - case 8: - if ((tdd_sfa>=2) || (tdd_sfa<=5)) sched_subframe=2; - else return; - break; - case 9: - if ((tdd_sfa==1) || (tdd_sfa==3) || (tdd_sfa==4)) sched_subframe=3; - else if (tdd_sfa==6) sched_subframe=4; - else return; - break; + uint16_t first_rb[MAX_NUM_CCs], i; + int CC_id; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc; + + start_meas(&mac->schedule_ulsch); + + int sched_subframe = (subframeP + 4) % 10; + + cc = &mac->common_channels[0]; + int tdd_sfa; + // for TDD: check subframes where we have to act and return if nothing should be done now + if (cc->tdd_Config) { + tdd_sfa = cc->tdd_Config->subframeAssignment; + switch (subframeP) { + case 0: + if ((tdd_sfa == 0) || (tdd_sfa == 3) || (tdd_sfa == 6)) + sched_subframe = 4; + else + return; + break; + case 1: + if ((tdd_sfa == 0) || (tdd_sfa == 1)) + sched_subframe = 7; + else if (tdd_sfa == 6) + sched_subframe = 8; + break; + default: + return; + + case 2: // Don't schedule UL in subframe 2 for TDD + return; + case 3: + if (tdd_sfa == 2) + sched_subframe = 7; + else + return; + break; + case 4: + if (tdd_sfa == 1) + sched_subframe = 8; + else + return; + break; + case 5: + if (tdd_sfa == 0) + sched_subframe = 9; + else if (tdd_sfa == 6) + sched_subframe = 3; + else + return; + break; + case 6: + if (tdd_sfa == 1) + sched_subframe = 2; + else if (tdd_sfa == 6) + sched_subframe = 3; + else + return; + break; + case 7: + return; + case 8: + if ((tdd_sfa >= 2) || (tdd_sfa <= 5)) + sched_subframe = 2; + else + return; + break; + case 9: + if ((tdd_sfa == 1) || (tdd_sfa == 3) || (tdd_sfa == 4)) + sched_subframe = 3; + else if (tdd_sfa == 6) + sched_subframe = 4; + else + return; + break; + } } - } - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - //leave out first RB for PUCCH - first_rb[CC_id] = 1; + //leave out first RB for PUCCH + first_rb[CC_id] = 1; - // UE data info; - // check which UE has data to transmit - // function to decide the scheduling - // e.g. scheduling_rslt = Greedy(granted_UEs, nb_RB) + // 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 - // + // 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 subframeP, 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?) + // output of scheduling, the UE numbers in RBs, where it is in the code??? + // check if RA (Msg3) is active in this subframeP, 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<NB_RA_PROC_MAX; i++) { - if ((cc->RA_template[i].RA_active == TRUE) && - (cc->RA_template[i].generate_rar == 0) && - (cc->RA_template[i].generate_Msg4 == 0) && - (cc->RA_template[i].wait_ack_Msg4 == 0) && - (cc->RA_template[i].Msg3_subframe == sched_subframe)) { - first_rb[CC_id]++; - // cc->RA_template[i].Msg3_subframe = -1; - break; - } + for (i = 0; i < NB_RA_PROC_MAX; i++) { + if ((cc->ra[i].state == WAITMSG3) && + (cc->ra[i].Msg3_subframe == sched_subframe)) { + first_rb[CC_id]++; + // cc->ray[i].Msg3_subframe = -1; + break; + } + } } - } - schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe,first_rb); + schedule_ulsch_rnti(module_idP, frameP, subframeP, sched_subframe, + first_rb); - stop_meas(&eNB->schedule_ulsch); + stop_meas(&mac->schedule_ulsch); } -void schedule_ulsch_rnti(module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - unsigned char sched_subframeP, - uint16_t *first_rb) +void +schedule_ulsch_rnti(module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + unsigned char sched_subframeP, uint16_t * first_rb) { - int UE_id; - uint8_t aggregation = 2; - rnti_t rnti = -1; - uint8_t round = 0; - uint8_t harq_pid = 0; - uint8_t status = 0; - uint8_t rb_table_index = -1; - uint32_t cqi_req,cshift,ndi,tpc; - int32_t normalized_rx_power; - int32_t target_rx_power=-90; - static int32_t tpc_accumulated=0; - int n; - int CC_id = 0; - int drop_ue=0; - int N_RB_UL; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list=&eNB->UE_list; - UE_TEMPLATE *UE_template; - UE_sched_ctrl *UE_sched_ctrl; - int sched_frame=frameP; - int rvidx_tab[4] = {0,2,3,1}; - - if (sched_subframeP<subframeP) sched_frame++; - - nfapi_hi_dci0_request_body_t *hi_dci0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; - - nfapi_ul_config_request_body_t *ul_req_tmp = &eNB->UL_req_tmp[CC_id][sched_subframeP].ul_config_request_body; - - LOG_D(MAC,"entering ulsch preprocesor\n"); - ulsch_scheduler_pre_processor(module_idP, - frameP, - subframeP, - first_rb); - - LOG_D(MAC,"exiting ulsch preprocesor\n"); - - eNB->HI_DCI0_req[CC_id].sfn_sf = (frameP<<4)+subframeP; - - // loop over all active UEs - for (UE_id=UE_list->head_ul; UE_id>=0; UE_id=UE_list->next_ul[UE_id]) { - - // don't schedule if Msg4 is not received yet - if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) { - LOG_D(MAC,"[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n", - module_idP,frameP,subframeP,UE_id); - continue; - } - - rnti = UE_RNTI(module_idP,UE_id); - - if (rnti==NOT_A_RNTI) { - LOG_W(MAC,"[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n", module_idP,frameP,subframeP,UE_id); - continue; - } - - drop_ue = 0; - /* let's drop the UE if get_eNB_UE_stats returns NULL when calling it with any of the UE's active UL CCs */ - /* TODO: refine? - - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - - if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) { - LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id); - drop_ue = 1; - break; - } - }*/ - if (drop_ue == 1) { + int UE_id; + uint8_t aggregation = 2; + rnti_t rnti = -1; + uint8_t round = 0; + uint8_t harq_pid = 0; + uint8_t status = 0; + uint8_t rb_table_index = -1; + uint32_t cqi_req, cshift, ndi, tpc; + int32_t normalized_rx_power; + int32_t target_rx_power = -90; + static int32_t tpc_accumulated = 0; + int n; + int CC_id = 0; + int drop_ue = 0; + int N_RB_UL; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + UE_list_t *UE_list = &mac->UE_list; + UE_TEMPLATE *UE_template; + UE_sched_ctrl *UE_sched_ctrl; + int sched_frame = frameP; + int rvidx_tab[4] = { 0, 2, 3, 1 }; + + if (sched_subframeP < subframeP) + sched_frame++; + + nfapi_hi_dci0_request_body_t *hi_dci0_req = + &mac->HI_DCI0_req[CC_id].hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; + + nfapi_ul_config_request_body_t *ul_req_tmp = + &mac->UL_req_tmp[CC_id][sched_subframeP].ul_config_request_body; + + LOG_D(MAC, "entering ulsch preprocesor\n"); + ulsch_scheduler_pre_processor(module_idP, frameP, subframeP, first_rb); + + LOG_D(MAC, "exiting ulsch preprocesor\n"); + + mac->HI_DCI0_req[CC_id].sfn_sf = (frameP << 4) + subframeP; + + // loop over all active UEs + for (UE_id = UE_list->head_ul; UE_id >= 0; + UE_id = UE_list->next_ul[UE_id]) { + + // don't schedule if Msg4 is not received yet + if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id]. + configured == FALSE) { + LOG_D(MAC, + "[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n", + module_idP, frameP, subframeP, UE_id); + continue; + } + + rnti = UE_RNTI(module_idP, UE_id); + + if (rnti == NOT_A_RNTI) { + LOG_W(MAC, "[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n", + module_idP, frameP, subframeP, UE_id); + continue; + } + + drop_ue = 0; + /* let's drop the UE if get_eNB_UE_stats returns NULL when calling it with any of the UE's active UL CCs */ + /* TODO: refine? + + for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { + CC_id = UE_list->ordered_ULCCids[n][UE_id]; + + if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) { + LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id); + drop_ue = 1; + break; + } + } */ + if (drop_ue == 1) { /* we can't come here, ulsch_scheduler_pre_processor won't put in the list a UE with no PHY context */ -abort(); - /* TODO: this is a hack. Sometimes the UE has no PHY context but - * is still present in the MAC with 'ul_failure_timer' = 0 and - * 'ul_out_of_sync' = 0. It seems wrong and the UE stays there forever. Let's - * start an UL out of sync procedure in this case. - * The root cause of this problem has to be found and corrected. - * In the meantime, this hack... - */ - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0 && - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0) { - LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: UE in weird state, let's put it 'out of sync'\n", - module_idP,frameP,subframeP,UE_id,rnti,CC_id); - // inform RRC of failure and clear timer - mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti); - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0; - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1; - } - continue; - } - - // loop over all active UL CC_ids for this UE - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth); - - /* - aggregation=get_aggregation(get_bw_index(module_idP,CC_id), - eNB_UE_stats->dl_cqi, - format0); - */ - - if (CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,aggregation,rnti)) { - LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id); - continue; // break; - } - - /* be sure that there are some free RBs */ - if (first_rb[CC_id] >= N_RB_UL-1) { - LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", - module_idP,frameP,subframeP,UE_id,rnti,CC_id); - continue; - } - - // if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel - - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - harq_pid = subframe2harqpid(&cc[CC_id],sched_frame,sched_subframeP); - round = UE_sched_ctrl->round_UL[CC_id][harq_pid]; - AssertFatal(round<8,"round %d > 7 for UE %d/%x\n",round,UE_id,rnti); - LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", - module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL); - - RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->ul_total_buffer; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]); - if (UE_is_to_be_scheduled(module_idP,CC_id,UE_id) > 0 || round > 0)// || ((frameP%10)==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 %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n", - module_idP,harq_pid,frameP,subframeP,UE_id,rnti,round,UE_template->ul_SR, - UE_sched_ctrl->ul_inactivity_timer, - - UE_sched_ctrl->ul_failure_timer, - - UE_sched_ctrl->cqi_req_timer); - // reset the scheduling request - UE_template->ul_SR = 0; - status = mac_eNB_get_rrc_status(module_idP,rnti); - if (status < RRC_CONNECTED) - cqi_req = 0; - else if (UE_sched_ctrl->cqi_req_timer>30) { - cqi_req = 1; - UE_sched_ctrl->cqi_req_timer=0; - } - else - cqi_req = 0; - - //power control - //compute the expected ULSCH RX power (for the stats) - - // this is the normalized RX power and this should be constant (regardless of mcs - normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id]; - target_rx_power = 178; - - // this assumes accumulated tpc - // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe; - if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case - ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around - { - UE_template->pusch_tpc_tx_frame=frameP; - UE_template->pusch_tpc_tx_subframe=subframeP; - if (normalized_rx_power>(target_rx_power+4)) { - tpc = 0; //-1 - tpc_accumulated--; - } else if (normalized_rx_power<(target_rx_power-4)) { - tpc = 2; //+1 - tpc_accumulated++; - } else { - tpc = 1; //0 - } - } else { - tpc = 1; //0 - } - //tpc = 1; - if (tpc!=1) { - LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", - module_idP,frameP,subframeP,harq_pid,tpc, - tpc_accumulated,normalized_rx_power,target_rx_power); - } - - // new transmission - if (round==0) { - - ndi = 1-UE_template->oldNDI_UL[harq_pid]; - UE_template->oldNDI_UL[harq_pid]=ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power; - UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; - UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS - if (UE_template->pre_allocated_rb_table_index_ul >=0) { - rb_table_index=UE_template->pre_allocated_rb_table_index_ul; - } else { - UE_template->mcs_UL[harq_pid]=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs); - rb_table_index=5; // for PHR - } - - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; - // buffer_occupancy = UE_template->ul_total_buffer; - - - while (((rb_table[rb_table_index]>(N_RB_UL-1-first_rb[CC_id])) || - (rb_table[rb_table_index]>45)) && - (rb_table_index>0)) { - rb_table_index--; - } - - UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; - // buffer_occupancy -= TBS; - - T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), - T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), - T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi)); - - if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) - LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n", - module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid], - first_rb[CC_id],rb_table[rb_table_index], - rb_table_index,UE_template->TBS_UL[harq_pid],harq_pid); - - // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) - //store for possible retransmission - UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; - UE_template->first_rb_ul[harq_pid] = first_rb[CC_id]; - - UE_sched_ctrl->ul_scheduled |= (1<<harq_pid); - if (UE_id == UE_list->head) - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled); - - // adjust total UL buffer status by TBS, wait for UL sdus to do final update - LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,UE_template->TBS_UL[harq_pid]); - if (UE_template->ul_total_buffer > UE_template->TBS_UL[harq_pid]) - UE_template->ul_total_buffer -= UE_template->TBS_UL[harq_pid]; - else - UE_template->ul_total_buffer = 0; - LOG_D(MAC,"ul_total_buffer, new %d\n", UE_template->ul_total_buffer); - // Cyclic shift for DM RS - cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) - // save it for a potential retransmission - UE_template->cshift[harq_pid] = cshift; - - hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi]; - memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_dci_pdu); - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template->DAI_ul[sched_subframeP]; - - eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++; - - LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); - - // Add UL_config PDUs - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], - cqi_req, - cc, - UE_template->physicalConfigDedicated, - get_tmode(module_idP,CC_id,UE_id), - eNB->ul_handle, - rnti, - first_rb[CC_id], // resource_block_start - rb_table[rb_table_index], // number_of_resource_blocks - UE_template->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - ndi, // new_data_indication - 0, // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - get_TBS_UL(UE_template->mcs_UL[harq_pid], - rb_table[rb_table_index]) - ); + abort(); + /* TODO: this is a hack. Sometimes the UE has no PHY context but + * is still present in the MAC with 'ul_failure_timer' = 0 and + * 'ul_out_of_sync' = 0. It seems wrong and the UE stays there forever. Let's + * start an UL out of sync procedure in this case. + * The root cause of this problem has to be found and corrected. + * In the meantime, this hack... + */ + if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0 && + UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0) { + LOG_W(MAC, + "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: UE in weird state, let's put it 'out of sync'\n", + module_idP, frameP, subframeP, UE_id, rnti, CC_id); + // inform RRC of failure and clear timer + mac_eNB_rrc_ul_failure(module_idP, CC_id, frameP, + subframeP, rnti); + UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; + } + continue; + } + // loop over all active UL CC_ids for this UE + for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + // This is the actual CC_id in the list + CC_id = UE_list->ordered_ULCCids[n][UE_id]; + N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth); + + /* + aggregation=get_aggregation(get_bw_index(module_idP,CC_id), + eNB_UE_stats->dl_cqi, + format0); + */ + + if (CCE_allocation_infeasible + (module_idP, CC_id, 1, subframeP, aggregation, rnti)) { + LOG_W(MAC, + "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", + module_idP, frameP, subframeP, UE_id, rnti, CC_id); + continue; // break; + } + + /* be sure that there are some free RBs */ + if (first_rb[CC_id] >= N_RB_UL - 1) { + LOG_W(MAC, + "[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", + module_idP, frameP, subframeP, UE_id, rnti, CC_id); + continue; + } + // if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel + + UE_template = &UE_list->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + harq_pid = + subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); + round = UE_sched_ctrl->round_UL[CC_id][harq_pid]; + AssertFatal(round < 8, "round %d > 7 for UE %d/%x\n", round, + UE_id, rnti); + LOG_D(MAC, + "[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", + module_idP, frameP, subframeP, harq_pid, UE_id, rnti, + CC_id, aggregation, N_RB_UL); + + RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * + 10) + + subframeP] = + UE_template->ul_total_buffer; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME + (VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, + RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * + 10) + + subframeP]); + if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) > 0 || round > 0) // || ((frameP%10)==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 %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n", + module_idP, harq_pid, frameP, subframeP, UE_id, rnti, + round, UE_template->ul_SR, + UE_sched_ctrl->ul_inactivity_timer, + UE_sched_ctrl->ul_failure_timer, + UE_sched_ctrl->cqi_req_timer); + // reset the scheduling request + UE_template->ul_SR = 0; + status = mac_eNB_get_rrc_status(module_idP, rnti); + if (status < RRC_CONNECTED) + cqi_req = 0; + else if (UE_sched_ctrl->cqi_req_timer > 30) { + cqi_req = 1; + UE_sched_ctrl->cqi_req_timer = 0; + } else + cqi_req = 0; + + //power control + //compute the expected ULSCH RX power (for the stats) + + // this is the normalized RX power and this should be constant (regardless of mcs + normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id]; + target_rx_power = 178; + + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = + UE_template->pusch_tpc_tx_frame * 10 + + UE_template->pusch_tpc_tx_subframe; + if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || //normal case + ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10)))) //frame wrap-around + { + UE_template->pusch_tpc_tx_frame = frameP; + UE_template->pusch_tpc_tx_subframe = subframeP; + if (normalized_rx_power > (target_rx_power + 4)) { + tpc = 0; //-1 + tpc_accumulated--; + } else if (normalized_rx_power < (target_rx_power - 4)) { + tpc = 2; //+1 + tpc_accumulated++; + } else { + tpc = 1; //0 + } + } else { + tpc = 1; //0 + } + //tpc = 1; + if (tpc != 1) { + LOG_D(MAC, + "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + module_idP, frameP, subframeP, harq_pid, tpc, + tpc_accumulated, normalized_rx_power, + target_rx_power); + } + // new transmission + if (round == 0) { + + ndi = 1 - UE_template->oldNDI_UL[harq_pid]; + UE_template->oldNDI_UL[harq_pid] = ndi; + UE_list->eNB_UE_stats[CC_id][UE_id]. + normalized_rx_power = normalized_rx_power; + UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = + target_rx_power; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = + UE_template->pre_assigned_mcs_ul; + UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul; //cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS + if (UE_template->pre_allocated_rb_table_index_ul >= 0) { + rb_table_index = + UE_template->pre_allocated_rb_table_index_ul; + } else { + UE_template->mcs_UL[harq_pid] = 10; //cmin (10, openair_daq_vars.target_ue_ul_mcs); + rb_table_index = 5; // for PHR + } + + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = + UE_template->mcs_UL[harq_pid]; + // buffer_occupancy = UE_template->ul_total_buffer; + + + while (((rb_table[rb_table_index] > + (N_RB_UL - 1 - first_rb[CC_id])) + || (rb_table[rb_table_index] > 45)) + && (rb_table_index > 0)) { + rb_table_index--; + } + + UE_template->TBS_UL[harq_pid] = + get_TBS_UL(UE_template->mcs_UL[harq_pid], + rb_table[rb_table_index]); + UE_list->eNB_UE_stats[CC_id][UE_id]. + total_rbs_used_rx += rb_table[rb_table_index]; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = + UE_template->TBS_UL[harq_pid]; + // buffer_occupancy -= TBS; + + T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), + T_INT(CC_id), T_INT(rnti), T_INT(frameP), + T_INT(subframeP), T_INT(harq_pid), + T_INT(UE_template->mcs_UL[harq_pid]), + T_INT(first_rb[CC_id]), + T_INT(rb_table[rb_table_index]), + T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi)); + + if (mac_eNB_get_rrc_status(module_idP, rnti) < + RRC_CONNECTED) + LOG_D(MAC, + "[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n", + module_idP, harq_pid, rnti, CC_id, frameP, + subframeP, UE_id, + UE_template->mcs_UL[harq_pid], + first_rb[CC_id], rb_table[rb_table_index], + rb_table_index, + UE_template->TBS_UL[harq_pid], harq_pid); + + // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) + //store for possible retransmission + UE_template->nb_rb_ul[harq_pid] = + rb_table[rb_table_index]; + UE_template->first_rb_ul[harq_pid] = first_rb[CC_id]; + + UE_sched_ctrl->ul_scheduled |= (1 << harq_pid); + if (UE_id == UE_list->head) + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME + (VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, + UE_sched_ctrl->ul_scheduled); + + // adjust total UL buffer status by TBS, wait for UL sdus to do final update + LOG_D(MAC, + "[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", + module_idP, CC_id, UE_id, rnti, + UE_template->ul_total_buffer, + UE_template->TBS_UL[harq_pid]); + if (UE_template->ul_total_buffer > + UE_template->TBS_UL[harq_pid]) + UE_template->ul_total_buffer -= + UE_template->TBS_UL[harq_pid]; + else + UE_template->ul_total_buffer = 0; + LOG_D(MAC, "ul_total_buffer, new %d\n", + UE_template->ul_total_buffer); + // Cyclic shift for DM RS + cshift = 0; // values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) + // save it for a potential retransmission + UE_template->cshift[harq_pid] = cshift; + + hi_dci0_pdu = + &hi_dci0_req->hi_dci0_pdu_list[mac->HI_DCI0_req + [CC_id]. + hi_dci0_request_body. + number_of_dci + + mac->HI_DCI0_req + [CC_id]. + hi_dci0_request_body. + number_of_hi]; + memset((void *) hi_dci0_pdu, 0, + sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->pdu_size = + 2 + sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = + NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = + aggregation; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = + 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8. + resource_block_start = first_rb[CC_id]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8. + number_of_resource_block = + rb_table[rb_table_index]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = + UE_template->mcs_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8. + cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8. + frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8. + new_data_indication_1 = ndi; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = + cqi_req; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = + UE_template->DAI_ul[sched_subframeP]; + + mac->HI_DCI0_req[CC_id].hi_dci0_request_body. + number_of_dci++; + + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, frameP, subframeP, UE_id, rnti, + sched_frame, sched_subframeP); + + // Add UL_config PDUs + fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb[CC_id], // resource_block_start + rb_table[rb_table_index], // number_of_resource_blocks + UE_template->mcs_UL[harq_pid], cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + ndi, // new_data_indication + 0, // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + get_TBS_UL + (UE_template-> + mcs_UL[harq_pid], + rb_table + [rb_table_index])); #ifdef Rel14 - if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], - UE_template->rach_resource_type>2 ? 2 : 1, - 1, //total_number_of_repetitions - 1, //repetition_number - (frameP*10)+subframeP); - } + if (UE_template->rach_resource_type > 0) { // This is a BL/CE UE allocation + fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], UE_template->rach_resource_type > 2 ? 2 : 1, 1, //total_number_of_repetitions + 1, //repetition_number + (frameP * + 10) + + subframeP); + } #endif - ul_req_tmp->number_of_pdus++; - eNB->ul_handle++; - - add_ue_ulsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_UL_SCHEDULED); - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id); - - // increment first rb for next UE allocation - first_rb[CC_id]+=rb_table[rb_table_index]; - } - else { // round > 0 => retransmission - T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), - T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), - T_INT(round)); - - // fill in NAK information - - hi_dci0_pdu = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi]; - memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2+sizeof(nfapi_hi_dci0_hi_pdu); - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = UE_template->first_rb_ul[harq_pid]; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = UE_template->cshift[harq_pid]; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; - hi_dci0_req->number_of_hi++; - LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, round %d)\n", - module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,UE_template->mcs_UL[harq_pid], - UE_template->first_rb_ul[harq_pid], UE_template->nb_rb_ul[harq_pid], - UE_template->TBS_UL[harq_pid],round); - // Add UL_config PDUs - LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], - cqi_req, - cc, - UE_template->physicalConfigDedicated, - get_tmode(module_idP,CC_id,UE_id), - eNB->ul_handle, - rnti, - UE_template->first_rb_ul[harq_pid], // resource_block_start - UE_template->nb_rb_ul[harq_pid], // number_of_resource_blocks - UE_template->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - UE_template->oldNDI_UL[harq_pid], // new_data_indication - rvidx_tab[round&3], // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - UE_template->TBS_UL[harq_pid] - ); + ul_req_tmp->number_of_pdus++; + mac->ul_handle++; + + add_ue_ulsch_info(module_idP, + CC_id, UE_id, subframeP, + S_UL_SCHEDULED); + + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", + module_idP, CC_id, frameP, subframeP, UE_id); + + // increment first rb for next UE allocation + first_rb[CC_id] += rb_table[rb_table_index]; + } else { // round > 0 => retransmission + T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, + T_INT(module_idP), T_INT(CC_id), T_INT(rnti), + T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), + T_INT(UE_template->mcs_UL[harq_pid]), + T_INT(first_rb[CC_id]), + T_INT(rb_table[rb_table_index]), T_INT(round)); + + // fill in NAK information + + hi_dci0_pdu = + &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req-> + number_of_dci + + hi_dci0_req-> + number_of_hi]; + memset((void *) hi_dci0_pdu, 0, + sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; + hi_dci0_pdu->pdu_size = + 2 + sizeof(nfapi_hi_dci0_hi_pdu); + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = + UE_template->first_rb_ul[harq_pid]; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8. + cyclic_shift_2_for_drms = + UE_template->cshift[harq_pid]; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; + hi_dci0_req->number_of_hi++; + LOG_D(MAC, + "[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, round %d)\n", + module_idP, harq_pid, rnti, CC_id, frameP, + subframeP, UE_id, UE_template->mcs_UL[harq_pid], + UE_template->first_rb_ul[harq_pid], + UE_template->nb_rb_ul[harq_pid], + UE_template->TBS_UL[harq_pid], round); + // Add UL_config PDUs + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, frameP, subframeP, UE_id, rnti, + sched_frame, sched_subframeP); + fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, UE_template->first_rb_ul[harq_pid], // resource_block_start + UE_template->nb_rb_ul[harq_pid], // number_of_resource_blocks + UE_template->mcs_UL[harq_pid], cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + UE_template->oldNDI_UL[harq_pid], // new_data_indication + rvidx_tab[round & 3], // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + UE_template-> + TBS_UL[harq_pid]); #ifdef Rel14 - if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], - UE_template->rach_resource_type>2 ? 2 : 1, - 1, //total_number_of_repetitions - 1, //repetition_number - (frameP*10)+subframeP); - } + if (UE_template->rach_resource_type > 0) { // This is a BL/CE UE allocation + fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp->ul_config_pdu_list[ul_req_tmp->number_of_pdus], UE_template->rach_resource_type > 2 ? 2 : 1, 1, //total_number_of_repetitions + 1, //repetition_number + (frameP * + 10) + + subframeP); + } #endif - ul_req_tmp->number_of_pdus++; - eNB->ul_handle++; - - }/* - else if (round > 0) { //we schedule a retransmission - - ndi = UE_template->oldNDI_UL[harq_pid]; - - if ((round&3)==0) { - mcs = openair_daq_vars.target_ue_ul_mcs; - } else { - mcs = rvidx_tab[round&3] + 28; //not correct for round==4! - - } - - LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, harq_pid %d, round %d)\n", - module_idP,UE_id,rnti,CC_id,frameP,subframeP,mcs, - first_rb[CC_id],UE_template->nb_rb_ul[harq_pid], - harq_pid, round); - - rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL, - first_rb[CC_id], - UE_template->nb_rb_ul[harq_pid]); - first_rb[CC_id]+=UE_template->nb_rb_ul[harq_pid]; // increment for next UE allocation - - UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission_rx+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx=UE_template->nb_rb_ul[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=UE_template->nb_rb_ul[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=mcs; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs; - } - */ - - } // UE_is_to_be_scheduled - } // loop over UE_id - } // loop of CC_id + ul_req_tmp->number_of_pdus++; + mac->ul_handle++; + + } /* + else if (round > 0) { //we schedule a retransmission + + ndi = UE_template->oldNDI_UL[harq_pid]; + + if ((round&3)==0) { + mcs = openair_daq_vars.target_ue_ul_mcs; + } else { + mcs = rvidx_tab[round&3] + 28; //not correct for round==4! + + } + + LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, harq_pid %d, round %d)\n", + module_idP,UE_id,rnti,CC_id,frameP,subframeP,mcs, + first_rb[CC_id],UE_template->nb_rb_ul[harq_pid], + harq_pid, round); + + rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL, + first_rb[CC_id], + UE_template->nb_rb_ul[harq_pid]); + first_rb[CC_id]+=UE_template->nb_rb_ul[harq_pid]; // increment for next UE allocation + + UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission_rx+=1; + UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx=UE_template->nb_rb_ul[harq_pid]; + UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=UE_template->nb_rb_ul[harq_pid]; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=mcs; + UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs; + } + */ + + } // UE_is_to_be_scheduled + } // loop over UE_id + } // loop of CC_id } diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h index f192cd7e127ef01b1ea66adc14c03c4d2217f7a3..50ea5634b93dd13ca57c40875e4fda4d9930e2a7 100644 --- a/openair2/LAYER2/MAC/extern.h +++ b/openair2/LAYER2/MAC/extern.h @@ -35,7 +35,7 @@ #ifdef USER_MODE //#include "stdio.h" -#endif //USER_MODE +#endif //USER_MODE #include "PHY/defs.h" #include "defs.h" @@ -56,8 +56,8 @@ extern UE_RRC_INST *UE_rrc_inst; extern UE_MAC_INST *UE_mac_inst; -extern eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 -extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 +extern eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 +extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 @@ -79,28 +79,26 @@ extern uint32_t RRC_CONNECTION_FLAG; extern uint8_t rb_table[34]; -extern DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; +extern DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; -extern DCI1A_5MHz_TDD_1_6_t RA_alloc_pdu; -extern DCI1A_5MHz_TDD_1_6_t DLSCH_alloc_pdu1A; -extern DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; +extern DCI1A_5MHz_TDD_1_6_t RA_alloc_pdu; +extern DCI1A_5MHz_TDD_1_6_t DLSCH_alloc_pdu1A; +extern DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; -extern DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; -extern DCI1_5MHz_TDD_t DLSCH_alloc_pdu; +extern DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; +extern DCI1_5MHz_TDD_t DLSCH_alloc_pdu; -extern DCI0_5MHz_FDD_t UL_alloc_pdu_fdd; +extern DCI0_5MHz_FDD_t UL_alloc_pdu_fdd; -extern DCI1A_5MHz_FDD_t DLSCH_alloc_pdu1A_fdd; -extern DCI1A_5MHz_FDD_t RA_alloc_pdu_fdd; -extern DCI1A_5MHz_FDD_t BCCH_alloc_pdu_fdd; +extern DCI1A_5MHz_FDD_t DLSCH_alloc_pdu1A_fdd; +extern DCI1A_5MHz_FDD_t RA_alloc_pdu_fdd; +extern DCI1A_5MHz_FDD_t BCCH_alloc_pdu_fdd; -extern DCI1A_5MHz_FDD_t CCCH_alloc_pdu_fdd; -extern DCI1_5MHz_FDD_t DLSCH_alloc_pdu_fdd; +extern DCI1A_5MHz_FDD_t CCCH_alloc_pdu_fdd; +extern DCI1_5MHz_FDD_t DLSCH_alloc_pdu_fdd; extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1; extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; -#endif //DEF_H - - +#endif //DEF_H diff --git a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h index 5b152a1138c80536876d0e83335368aeb90392c9..d3170aaf919e2a24e4599399729b4078e9d6c254 100644 --- a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h +++ b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_agent_mac_proto.h * \brief MAC functions for FlexRAN agent @@ -39,150 +39,178 @@ /* * slice specific scheduler */ -typedef void (*slice_scheduler)(module_id_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); +typedef void (*slice_scheduler) (module_id_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * top level flexran scheduler used by the eNB scheduler */ -void flexran_schedule_ue_spec_default(mid_t mod_id, - uint32_t frame, +void flexran_schedule_ue_spec_default(mid_t mod_id, + uint32_t frame, uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * slice specific scheduler for embb */ void -flexran_schedule_ue_spec_embb(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); +flexran_schedule_ue_spec_embb(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * slice specific scheduler for urllc */ void -flexran_schedule_ue_spec_urllc(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); +flexran_schedule_ue_spec_urllc(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * slice specific scheduler for mmtc */ void -flexran_schedule_ue_spec_mmtc(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); +flexran_schedule_ue_spec_mmtc(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * slice specific scheduler for best effort traffic */ void -flexran_schedule_ue_spec_be(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); +flexran_schedule_ue_spec_be(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * common flexran scheduler function */ void -flexran_schedule_ue_spec_common(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info); - -uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, - int total_rbs); - -int flexran_slice_member(int UE_id, - int slice_id); - -int flexran_slice_maxmcs(int slice_id) ; - -void _store_dlsch_buffer (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframeP); - - -void _assign_rbs_required (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframe, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES], - int min_rb_unit[MAX_NUM_CCs]); - -void _dlsch_scheduler_pre_processor (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframeP, - int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag); - -void _dlsch_scheduler_pre_processor_reset (int module_idP, - int UE_id, - uint8_t CC_id, - int frameP, - int subframeP, - int N_RBG, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]); - -void _dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int transmission_mode, - int min_rb_unit, - uint8_t N_RB_DL, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]); +flexran_schedule_ue_spec_common(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); + +uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs); + +int flexran_slice_member(int UE_id, int slice_id); + +int flexran_slice_maxmcs(int slice_id); + +void _store_dlsch_buffer(module_id_t Mod_id, + int slice_id, + frame_t frameP, sub_frame_t subframeP); + + +void _assign_rbs_required(module_id_t Mod_id, + int slice_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t + nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_allowed_slice[MAX_NUM_CCs] + [MAX_NUM_SLICES], int min_rb_unit[MAX_NUM_CCs]); + +void _dlsch_scheduler_pre_processor(module_id_t Mod_id, + int slice_id, + frame_t frameP, + sub_frame_t subframeP, + int N_RBG[MAX_NUM_CCs], + int *mbsfn_flag); + +void _dlsch_scheduler_pre_processor_reset(int module_idP, + int UE_id, + uint8_t CC_id, + int frameP, + int subframeP, + int N_RBG, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs][NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_allowed_slice[MAX_NUM_CCs] + [MAX_NUM_SLICES], + unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], + unsigned char + MIMO_mode_indicator[MAX_NUM_CCs] + [N_RBG_MAX]); + +void _dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + int transmission_mode, + int min_rb_unit, + uint8_t N_RB_DL, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], + unsigned char + MIMO_mode_indicator + [MAX_NUM_CCs][N_RBG_MAX]); /* * Default scheduler used by the eNB agent */ -void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe, - int *mbsfn_flag, Protocol__FlexranMessage **dl_info); +void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, + uint32_t subframe, int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); /* * Data plane function for applying the DL decisions of the scheduler */ -void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, - Protocol__FlexranMessage *dl_scheduling_info); +void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage * + dl_scheduling_info); /* * Data plane function for applying the UE specific DL decisions of the scheduler */ -void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, - uint32_t n_dl_ue_data, Protocol__FlexDlData **dl_ue_data); +void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + uint32_t n_dl_ue_data, + Protocol__FlexDlData ** + dl_ue_data); /* * Data plane function for filling the DCI structure */ -void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, Protocol__FlexDlDci *dl_dci); +void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, + Protocol__FlexDlDci * dl_dci); #endif diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c index 018d490f4430e696e70870383eb72c8b2d18e049..44052a8749191780e5c6c62c39935bfa91081792 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_agent_scheduler_dataplane.c * \brief data plane procedures related to eNB scheduling @@ -57,495 +57,532 @@ #include "flexran_agent_common.h" -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus + +void +flexran_apply_dl_scheduling_decisions(mid_t mod_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage * + dl_scheduling_info) +{ + + Protocol__FlexDlMacConfig *mac_config = + dl_scheduling_info->dl_mac_config_msg; + + // Check if there is anything to schedule for random access + if (mac_config->n_dl_rar > 0) { + /*TODO: call the random access data plane function */ + } + // Check if there is anything to schedule for paging/broadcast + if (mac_config->n_dl_broadcast > 0) { + /*TODO: call the broadcast/paging data plane function */ + } + // Check if there is anything to schedule for the UEs + if (mac_config->n_dl_ue_data > 0) { + flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, + mbsfn_flag, + mac_config-> + n_dl_ue_data, + mac_config->dl_ue_data); + } + +} + -void flexran_apply_dl_scheduling_decisions(mid_t mod_id, +void +flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, - Protocol__FlexranMessage *dl_scheduling_info) { - - Protocol__FlexDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg; - - // Check if there is anything to schedule for random access - if (mac_config->n_dl_rar > 0) { - /*TODO: call the random access data plane function*/ - } - - // Check if there is anything to schedule for paging/broadcast - if (mac_config->n_dl_broadcast > 0) { - /*TODO: call the broadcast/paging data plane function*/ - } - - // Check if there is anything to schedule for the UEs - if (mac_config->n_dl_ue_data > 0) { - flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag, - mac_config->n_dl_ue_data, mac_config->dl_ue_data); - } - -} + uint32_t n_dl_ue_data, + Protocol__FlexDlData ** + dl_ue_data) +{ + + uint8_t CC_id; + int UE_id; + mac_rlc_status_resp_t rlc_status; + unsigned char ta_len = 0; + unsigned char header_len = 0, header_len_tmp = 0; + unsigned char sdu_lcids[11], offset, num_sdus = 0; + uint16_t nb_rb; + uint16_t TBS, sdu_lengths[11], rnti, padding = 0, post_padding = 0; + unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; + uint8_t round = 0; + uint8_t harq_pid = 0; + // LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; + LTE_eNB_UE_stats *eNB_UE_stats = NULL; + uint16_t sdu_length_total = 0; + short ta_update = 0; + eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; + UE_list_t *UE_list = &eNB->UE_list; + // static int32_t tpc_accumulated=0; + UE_sched_ctrl *ue_sched_ctl; + + int last_sdu_header_len = 0; + + int i, j; + + Protocol__FlexDlData *dl_data; + Protocol__FlexDlDci *dl_dci; + + uint32_t rlc_size, n_lc, lcid; + + // For each UE-related command + for (i = 0; i < n_dl_ue_data; i++) { + + dl_data = dl_ue_data[i]; + dl_dci = dl_data->dl_dci; + + CC_id = dl_data->serv_cell_index; + // frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); + + rnti = dl_data->rnti; + UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti); + + round = dl_dci->rv[0]; + harq_pid = dl_dci->harq_process; + + //LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] Scheduling harq %d\n", frame, subframe, harq_pid); + // LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Now scheduling harq_pid %d (round %d)\n", frame, subframe, harq_pid, round); + + // If this is a new transmission + if (round == 0) { + // First we have to deal with the creation of the PDU based on the message instructions + rlc_status.bytes_in_buffer = 0; + + TBS = dl_dci->tbs_size[0]; + + if (dl_data->n_ce_bitmap > 0) { + //Check if there is TA command and set the length appropriately + ta_len = + (dl_data-> + ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 2 + : 0; + } + + num_sdus = 0; + sdu_length_total = 0; + + n_lc = dl_data->n_rlc_pdu; + // Go through each one of the channel commands and create SDUs + header_len = 0; + last_sdu_header_len = 0; + for (j = 0; j < n_lc; j++) { + sdu_lengths[j] = 0; + lcid = + dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->logical_channel_id; + rlc_size = dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->size; + LOG_D(MAC, + "[TEST] [eNB %d] [Frame %d] [Subframe %d], LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + mod_id, frame, subframe, lcid, CC_id, rlc_size); + if (rlc_size > 0) { + + rlc_status = mac_rlc_status_ind(mod_id, + rnti, + mod_id, + frame, + subframe, + ENB_FLAG_YES, + MBMS_FLAG_NO, lcid, 0); + + if (rlc_status.bytes_in_buffer > 0) { + + if (rlc_status.bytes_in_buffer < rlc_size) { + rlc_size = rlc_status.bytes_in_buffer; + } + + if (rlc_size <= 2) { + rlc_size = 3; + } + + rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, rlc_size); // transport block set size + + LOG_D(MAC, + "[TEST] RLC can give %d bytes for LCID %d during second call\n", + rlc_status.bytes_in_buffer, lcid); + + if (rlc_status.bytes_in_buffer > 0) { + + sdu_lengths[j] = mac_rlc_data_req(mod_id, rnti, mod_id, frame, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, rlc_size, //not used + (char *) + &dlsch_buffer + [sdu_length_total]); + + LOG_D(MAC, + "[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n", + mod_id, lcid, CC_id, sdu_lengths[j]); + sdu_length_total += sdu_lengths[j]; + sdu_lcids[j] = lcid; + + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] + += 1; + UE_list-> + eNB_UE_stats[CC_id][UE_id].num_bytes_tx + [lcid] += sdu_lengths[j]; + + if (sdu_lengths[j] < 128) { + header_len += 2; + last_sdu_header_len = 2; + } else { + header_len += 3; + last_sdu_header_len = 3; + } + num_sdus++; + } + } + } + } // SDU creation end + + + if (((sdu_length_total + header_len + ta_len) > 0)) { + + header_len_tmp = header_len; + + // If we have only a single SDU, header length becomes 1 + if ((num_sdus) == 1) { + //if (header_len == 2 || header_len == 3) { + header_len = 1; + } else { + header_len = (header_len - last_sdu_header_len) + 1; + } + + // If we need a 1 or 2 bit padding or no padding at all + if ((TBS - header_len - sdu_length_total - ta_len) <= 2 || (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow + padding = + (TBS - header_len - sdu_length_total - ta_len); + post_padding = 0; + } else { // The last sdu needs to have a length field, since we add padding + padding = 0; + header_len = header_len_tmp; + post_padding = TBS - sdu_length_total - header_len - ta_len; // 1 is for the postpadding header + } + + if (ta_len > 0) { + // Reset the measurement + ta_update = flexran_get_TA(mod_id, UE_id, CC_id); + ue_sched_ctl->ta_timer = 20; + eNB_UE_stats->timing_advance_update = 0; + } else { + ta_update = 0; + } + + // If there is nothing to schedule, just leave + if ((sdu_length_total) <= 0) { + harq_pid_updated[UE_id][harq_pid] = 1; + harq_pid_round[UE_id][harq_pid] = 0; + continue; + } + // LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] TBS is %d and bytes are %d\n", frame, subframe, TBS, sdu_length_total); + + offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, post_padding); + -void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - uint32_t n_dl_ue_data, - Protocol__FlexDlData **dl_ue_data) { - - uint8_t CC_id; - int UE_id; - mac_rlc_status_resp_t rlc_status; - unsigned char ta_len=0; - unsigned char header_len = 0, header_len_tmp = 0; - unsigned char sdu_lcids[11],offset,num_sdus=0; - uint16_t nb_rb; - uint16_t TBS, sdu_lengths[11],rnti,padding=0,post_padding=0; - unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; - uint8_t round = 0; - uint8_t harq_pid = 0; - // LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; - LTE_eNB_UE_stats *eNB_UE_stats = NULL; - uint16_t sdu_length_total = 0; - short ta_update = 0; - eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; - UE_list_t *UE_list = &eNB->UE_list; - // static int32_t tpc_accumulated=0; - UE_sched_ctrl *ue_sched_ctl; - - int last_sdu_header_len = 0; - - int i, j; - - Protocol__FlexDlData *dl_data; - Protocol__FlexDlDci *dl_dci; - - uint32_t rlc_size, n_lc, lcid; - - // For each UE-related command - for (i = 0; i < n_dl_ue_data; i++) { - - dl_data = dl_ue_data[i]; - dl_dci = dl_data->dl_dci; - - CC_id = dl_data->serv_cell_index; - // frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); - - rnti = dl_data->rnti; - UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); - - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti); - - round = dl_dci->rv[0]; - harq_pid = dl_dci->harq_process; - - //LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] Scheduling harq %d\n", frame, subframe, harq_pid); - // LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Now scheduling harq_pid %d (round %d)\n", frame, subframe, harq_pid, round); - - // If this is a new transmission - if (round == 0) { - // First we have to deal with the creation of the PDU based on the message instructions - rlc_status.bytes_in_buffer = 0; - - TBS = dl_dci->tbs_size[0]; - - if (dl_data->n_ce_bitmap > 0) { - //Check if there is TA command and set the length appropriately - ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 2 : 0; - } - - num_sdus = 0; - sdu_length_total = 0; - - n_lc = dl_data->n_rlc_pdu; - // Go through each one of the channel commands and create SDUs - header_len = 0; - last_sdu_header_len = 0; - for (j = 0; j < n_lc; j++) { - sdu_lengths[j] = 0; - lcid = dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->logical_channel_id; - rlc_size = dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->size; - LOG_D(MAC,"[TEST] [eNB %d] [Frame %d] [Subframe %d], LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - mod_id, frame, subframe, lcid, CC_id, rlc_size); - if (rlc_size > 0) { - - rlc_status = mac_rlc_status_ind(mod_id, - rnti, - mod_id, - frame, - subframe, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - 0); - - if (rlc_status.bytes_in_buffer > 0) { - - if (rlc_status.bytes_in_buffer < rlc_size) { - rlc_size = rlc_status.bytes_in_buffer; - } - if (rlc_size <= 2) { - rlc_size = 3; - } - - rlc_status = mac_rlc_status_ind(mod_id, - rnti, - mod_id, - frame, - subframe, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - rlc_size); // transport block set size - - LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid); - - if (rlc_status.bytes_in_buffer > 0) { - - sdu_lengths[j] = mac_rlc_data_req(mod_id, - rnti, - mod_id, - frame, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - rlc_size, //not used - (char *)&dlsch_buffer[sdu_length_total]); - - LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]); - sdu_length_total += sdu_lengths[j]; - sdu_lcids[j] = lcid; - - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[j]; - - if (sdu_lengths[j] < 128) { - header_len += 2; - last_sdu_header_len = 2; - } else { - header_len += 3; - last_sdu_header_len = 3; - } - num_sdus++; + +#ifdef DEBUG_eNB_SCHEDULER + 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"); +#endif + // cycle through SDUs and place in dlsch_buffer + memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id]. + 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++) { + UE_list->DLSCH_pdu[CC_id][0][UE_id].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 (opt_enabled == 1) { + trace_pdu(1, + (uint8_t *) + UE_list->DLSCH_pdu[CC_id][0][UE_id]. + payload[0], TBS, mod_id, 3, UE_RNTI(mod_id, + UE_id), + eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n", + mod_id, CC_id, frame, UE_RNTI(mod_id, UE_id), + TBS); + } + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; + UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi = + eNB_UE_stats->DL_cqi[0]; + + UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti; + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = + mac_eNB_get_rrc_status(mod_id, rnti); + UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; + UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; + + //nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + //Find the number of resource blocks and set them to the template for retransmissions + nb_rb = get_min_rb_unit(mod_id, CC_id); + uint16_t stats_tbs = + mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb); + + while (stats_tbs < TBS) { + nb_rb += get_min_rb_unit(mod_id, CC_id); + stats_tbs = + mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb); + } + + // LOG_I(FLEXRAN_AGENT, "The MCS was %d\n", dl_dci->mcs[0]); + + UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += + nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = + dl_dci->mcs[0]; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = + dl_dci->mcs[0]; + UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; + + UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes = + TBS - sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes += + sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes += TBS; + UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus += 1; + + //eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]]; + //eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + } else { + LOG_D(FLEXRAN_AGENT, + "No need to schedule a dci after all. Just drop it\n"); + harq_pid_updated[UE_id][harq_pid] = 1; + harq_pid_round[UE_id][harq_pid] = 0; + continue; } - } - } - } // SDU creation end - - - if (((sdu_length_total + header_len + ta_len) > 0)) { - - header_len_tmp = header_len; - - // If we have only a single SDU, header length becomes 1 - if ((num_sdus) == 1) { - //if (header_len == 2 || header_len == 3) { - header_len = 1; } else { - header_len = (header_len - last_sdu_header_len) + 1; - } - - // If we need a 1 or 2 bit padding or no padding at all - if ((TBS - header_len - sdu_length_total - ta_len) <= 2 - || (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow - padding = (TBS - header_len - sdu_length_total - ta_len); - post_padding = 0; - } else { // The last sdu needs to have a length field, since we add padding - padding = 0; - header_len = header_len_tmp; - post_padding = TBS - sdu_length_total - header_len - ta_len; // 1 is for the postpadding header - } - - if (ta_len > 0) { - // Reset the measurement - ta_update = flexran_get_TA(mod_id, UE_id, CC_id); - ue_sched_ctl->ta_timer = 20; - eNB_UE_stats->timing_advance_update = 0; - } else { - ta_update = 0; + // No need to create anything apart of DCI in case of retransmission + /*TODO: Must add these */ + // eNB_UE_stats->dlsch_trials[round]++; + //UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; + //UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; + //UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; + //UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id]; } - // If there is nothing to schedule, just leave - if ((sdu_length_total) <= 0) { - harq_pid_updated[UE_id][harq_pid] = 1; - harq_pid_round[UE_id][harq_pid] = 0; - continue; - } + // UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0]; + // eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0]; - // LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] TBS is %d and bytes are %d\n", frame, subframe, TBS, sdu_length_total); - - offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); + //Fill the proper DCI of OAI + flexran_fill_oai_dci(mod_id, CC_id, rnti, dl_dci); + } +} - +void +flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, + Protocol__FlexDlDci * dl_dci) +{ + void *DLSCH_dci = NULL; + DCI_PDU *DCI_pdu; - -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n"); - - for (i=0; i<16; i++) { - LOG_T(MAC,"%x.",dlsch_buffer[i]); + unsigned char harq_pid = 0; + // unsigned char round = 0; + LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; + int size_bits = 0, size_bytes = 0; + eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; + UE_list_t *UE_list = &eNB->UE_list; + LTE_eNB_UE_stats *eNB_UE_stats = NULL; + + int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); + + uint32_t format; + + harq_pid = dl_dci->harq_process; + // round = dl_dci->rv[0]; + + // Note this code is for a specific DCI format + DLSCH_dci = + (void *) UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid]; + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; + + frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); + + if (dl_dci->has_tpc == 1) { + // Check if tpc has been set and reset measurement */ + if ((dl_dci->tpc == 0) || (dl_dci->tpc == 2)) { + eNB_UE_stats = + mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti); + eNB_UE_stats->Po_PUCCH_update = 0; } - - LOG_T(MAC,"\n"); -#endif - // cycle through SDUs and place in dlsch_buffer - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].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++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); + } + + + switch (frame_parms[CC_id]->N_RB_DL) { + case 6: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_TDD_1(DCI1_1_5MHz_TDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_1_5MHz_TDD_t); + size_bits = sizeof_DCI1_1_5MHz_TDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_FDD_1(DCI1_1_5MHz_FDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_1_5MHz_FDD_t); + size_bits = sizeof_DCI1_1_5MHz_FDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } + } + break; + case 25: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_TDD_1(DCI1_5MHz_TDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_5MHz_TDD_t); + size_bits = sizeof_DCI1_5MHz_TDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_FDD_1(DCI1_5MHz_FDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_5MHz_FDD_t); + size_bits = sizeof_DCI1_5MHz_FDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } } - - //eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff); - if (opt_enabled == 1) { - trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - TBS, mod_id, 3, UE_RNTI(mod_id, UE_id), - eNB->frame, eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n", - mod_id, CC_id, frame, UE_RNTI(mod_id,UE_id), TBS); + break; + case 50: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_TDD_1(DCI1_10MHz_TDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_10MHz_TDD_t); + size_bits = sizeof_DCI1_10MHz_TDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_FDD_1(DCI1_10MHz_FDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_10MHz_FDD_t); + size_bits = sizeof_DCI1_10MHz_FDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } } - - // store stats - eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; - eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0]; - - UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti; - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(mod_id, rnti); - UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; - UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; - - //nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - //Find the number of resource blocks and set them to the template for retransmissions - nb_rb = get_min_rb_unit(mod_id, CC_id); - uint16_t stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb); - - while (stats_tbs < TBS) { - nb_rb += get_min_rb_unit(mod_id, CC_id); - stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb); + break; + case 100: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_TDD_1(DCI1_20MHz_TDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_20MHz_TDD_t); + size_bits = sizeof_DCI1_20MHz_TDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { + FILL_DCI_FDD_1(DCI1_20MHz_FDD_t, DLSCH_dci, dl_dci); + size_bytes = sizeof(DCI1_20MHz_FDD_t); + size_bits = sizeof_DCI1_20MHz_FDD_t; + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { + //TODO + } else if (dl_dci->format == + PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { + //TODO + } } - - // LOG_I(FLEXRAN_AGENT, "The MCS was %d\n", dl_dci->mcs[0]); - - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=dl_dci->mcs[0]; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=dl_dci->mcs[0]; - UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; - - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS - sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; - - //eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]]; - //eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - } else { - LOG_D(FLEXRAN_AGENT, "No need to schedule a dci after all. Just drop it\n"); - harq_pid_updated[UE_id][harq_pid] = 1; - harq_pid_round[UE_id][harq_pid] = 0; - continue; - } - } else { - // No need to create anything apart of DCI in case of retransmission - /*TODO: Must add these */ - // eNB_UE_stats->dlsch_trials[round]++; - //UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; - //UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; - //UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; - //UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id]; + break; } - // UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0]; - // eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0]; - - //Fill the proper DCI of OAI - flexran_fill_oai_dci(mod_id, CC_id, rnti, dl_dci); - } -} -void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, - Protocol__FlexDlDci *dl_dci) { - - void *DLSCH_dci = NULL; - DCI_PDU *DCI_pdu; - - unsigned char harq_pid = 0; - // unsigned char round = 0; - LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; - int size_bits = 0, size_bytes = 0; - eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; - UE_list_t *UE_list = &eNB->UE_list; - LTE_eNB_UE_stats *eNB_UE_stats = NULL; - - int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); - - uint32_t format; - - harq_pid = dl_dci->harq_process; - // round = dl_dci->rv[0]; - - // Note this code is for a specific DCI format - DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid]; - DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; - - frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); - - if (dl_dci->has_tpc == 1) { - // Check if tpc has been set and reset measurement */ - if ((dl_dci->tpc == 0) || (dl_dci->tpc == 2)) { - eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti); - eNB_UE_stats->Po_PUCCH_update = 0; - } - } - - - switch (frame_parms[CC_id]->N_RB_DL) { - case 6: - if (frame_parms[CC_id]->frame_type == TDD) { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_TDD_1(DCI1_1_5MHz_TDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_1_5MHz_TDD_t); - size_bits = sizeof_DCI1_1_5MHz_TDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } else { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_FDD_1(DCI1_1_5MHz_FDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_1_5MHz_FDD_t); - size_bits = sizeof_DCI1_1_5MHz_FDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } - break; - case 25: - if (frame_parms[CC_id]->frame_type == TDD) { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_TDD_1(DCI1_5MHz_TDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_5MHz_TDD_t); - size_bits = sizeof_DCI1_5MHz_TDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } else { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_FDD_1(DCI1_5MHz_FDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_5MHz_FDD_t); - size_bits = sizeof_DCI1_5MHz_FDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } + //Set format to the proper type + switch (dl_dci->format) { + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1: + format = format1; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1A: + format = format1A; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1B: + format = format1B; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1C: + format = format1C; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D: + format = format1E_2A_M10PRB; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2: + format = format2; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A: + format = format2A; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2B: + format = format2B; + break; + case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_3: + format = 3; + break; + default: + /*TODO: Need to deal with unsupported DCI type */ + return; } - break; - case 50: - if (frame_parms[CC_id]->frame_type == TDD) { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_TDD_1(DCI1_10MHz_TDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_10MHz_TDD_t); - size_bits = sizeof_DCI1_10MHz_TDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } else { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_FDD_1(DCI1_10MHz_FDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_10MHz_FDD_t); - size_bits = sizeof_DCI1_10MHz_FDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } - break; - case 100: - if (frame_parms[CC_id]->frame_type == TDD) { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_TDD_1(DCI1_20MHz_TDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_20MHz_TDD_t); - size_bits = sizeof_DCI1_20MHz_TDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } else { - if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) { - FILL_DCI_FDD_1(DCI1_20MHz_FDD_t, DLSCH_dci, dl_dci); - size_bytes = sizeof(DCI1_20MHz_FDD_t); - size_bits = sizeof_DCI1_20MHz_FDD_t; - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) { - //TODO - } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) { - //TODO - } - } - break; - } - - //Set format to the proper type - switch(dl_dci->format) { - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1: - format = format1; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1A: - format = format1A; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1B: - format = format1B; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1C: - format = format1C; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D: - format = format1E_2A_M10PRB; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2: - format = format2; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A: - format = format2A; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2B: - format = format2B; - break; - case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_3: - format = 3; - break; - default: - /*TODO: Need to deal with unsupported DCI type*/ - return; - } - - add_ue_spec_dci(DCI_pdu, - DLSCH_dci, - rnti, - size_bytes, - dl_dci->aggr_level, - size_bits, - format, - 0); + + add_ue_spec_dci(DCI_pdu, + DLSCH_dci, + rnti, + size_bytes, dl_dci->aggr_level, size_bits, format, 0); } diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c index ee0e7c55829672ba8bf28b62abd77f0903885cdd..3a491bd7ea8488d31953d8084935517a6ab81e19 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_agent_scheduler_dlsch_ue.c * \brief procedures related to eNB for the DLSCH transport channel @@ -58,10 +58,10 @@ #include "flexran_agent_mac.h" #include <dlfcn.h> -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #define ENABLE_MAC_PAYLOAD_DEBUG @@ -74,14 +74,14 @@ /*!\brief UE ULSCH scheduling states*/ typedef enum { - MIN_SLICE_STRATEGY = 0, - SLICE_MASK, - UEID_TO_SLICEID, - MAX_SLICE_STRATEGY + MIN_SLICE_STRATEGY = 0, + SLICE_MASK, + UEID_TO_SLICEID, + MAX_SLICE_STRATEGY } SLICING_STRATEGY; // this assumes a max of of 16 UE per eNB/CC -#define SLICE0_MASK 0x000f +#define SLICE0_MASK 0x000f #define SLICE1_MASK 0x00f0 #define SLICE2_MASK 0x0f00 #define SLICE3_MASK 0xf000 @@ -96,26 +96,28 @@ int slicing_strategy = UEID_TO_SLICEID; int slicing_strategy_current = UEID_TO_SLICEID; // RB share for each slice for past and current time -float slice_percentage[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0}; -float slice_percentage_current[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0}; +float slice_percentage[MAX_NUM_SLICES] = { 1.0, 0.0, 0.0, 0.0 }; +float slice_percentage_current[MAX_NUM_SLICES] = { 1.0, 0.0, 0.0, 0.0 }; + float total_slice_percentage = 0; // MAX MCS for each slice for past and current time -int slice_maxmcs[MAX_NUM_SLICES] = {28, 28, 28, 28}; -int slice_maxmcs_current[MAX_NUM_SLICES] = {28, 28, 28, 28}; +int slice_maxmcs[MAX_NUM_SLICES] = { 28, 28, 28, 28 }; +int slice_maxmcs_current[MAX_NUM_SLICES] = { 28, 28, 28, 28 }; -int update_dl_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1}; -int update_dl_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1}; +int update_dl_scheduler[MAX_NUM_SLICES] = { 1, 1, 1, 1 }; +int update_dl_scheduler_current[MAX_NUM_SLICES] = { 1, 1, 1, 1 }; // name of available scheduler -char *dl_scheduler_type[MAX_NUM_SLICES] = {"flexran_schedule_ue_spec_embb", - "flexran_schedule_ue_spec_urllc", - "flexran_schedule_ue_spec_mmtc", - "flexran_schedule_ue_spec_be" // best effort +char *dl_scheduler_type[MAX_NUM_SLICES] = + { "flexran_schedule_ue_spec_embb", + "flexran_schedule_ue_spec_urllc", + "flexran_schedule_ue_spec_mmtc", + "flexran_schedule_ue_spec_be" // best effort }; // pointer to the slice specific scheduler -slice_scheduler slice_sched[MAX_NUM_SLICES] = {0}; +slice_scheduler slice_sched[MAX_NUM_SLICES] = { 0 }; /** @@ -125,585 +127,695 @@ slice_scheduler slice_sched[MAX_NUM_SLICES] = {0}; // This function stores the downlink buffer for all the logical channels -void _store_dlsch_buffer (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframeP) +void +_store_dlsch_buffer(module_id_t Mod_id, + int slice_id, frame_t frameP, sub_frame_t subframeP) { - int UE_id,i; - rnti_t rnti; - mac_rlc_status_resp_t rlc_status; - UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; - UE_TEMPLATE *UE_template; - - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id]; - - // clear logical channel interface variables - UE_template->dl_buffer_total = 0; - UE_template->dl_pdus_total = 0; - - for(i=0; i< MAX_NUM_LCID; i++) { - UE_template->dl_buffer_info[i]=0; - UE_template->dl_pdus_in_buffer[i]=0; - UE_template->dl_buffer_head_sdu_creation_time[i]=0; - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i]=0; - } + int UE_id, i; + rnti_t rnti; + mac_rlc_status_resp_t rlc_status; + UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; + UE_TEMPLATE *UE_template; + + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; + + if (flexran_slice_member(UE_id, slice_id) == 0) + continue; - rnti = UE_RNTI(Mod_id,UE_id); + UE_template = + &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; - for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels + // clear logical channel interface variables + UE_template->dl_buffer_total = 0; + UE_template->dl_pdus_total = 0; + + for (i = 0; i < MAX_NUM_LCID; i++) { + UE_template->dl_buffer_info[i] = 0; + UE_template->dl_pdus_in_buffer[i] = 0; + UE_template->dl_buffer_head_sdu_creation_time[i] = 0; + UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = 0; + } - rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); - UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel - UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; - UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; - UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max, - rlc_status.head_sdu_creation_time ); - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send; - UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented; - UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer - UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[i]; + rnti = UE_RNTI(Mod_id, UE_id); + + for (i = 0; i < MAX_NUM_LCID; i++) { // loop over all the logical channels + + rlc_status = + mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP, + ENB_FLAG_YES, MBMS_FLAG_NO, i, 0); + UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel + UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; + UE_template->dl_buffer_head_sdu_creation_time[i] = + rlc_status.head_sdu_creation_time; + UE_template->dl_buffer_head_sdu_creation_time_max = + cmax(UE_template->dl_buffer_head_sdu_creation_time_max, + rlc_status.head_sdu_creation_time); + UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = + rlc_status.head_sdu_remaining_size_to_send; + UE_template->dl_buffer_head_sdu_is_segmented[i] = + rlc_status.head_sdu_is_segmented; + UE_template->dl_buffer_total += UE_template->dl_buffer_info[i]; //storing the total dlsch buffer + UE_template->dl_pdus_total += + UE_template->dl_pdus_in_buffer[i]; #ifdef DEBUG_eNB_SCHEDULER - /* note for dl_buffer_head_sdu_remaining_size_to_send[i] : - * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent - */ - if (UE_template->dl_buffer_info[i]>0) - LOG_D(MAC, - "[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", - Mod_id, slice_id,frameP, subframeP, UE_id, - i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i], - UE_template->dl_buffer_head_sdu_creation_time[i], - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i], - UE_template->dl_buffer_head_sdu_is_segmented[i] - ); + /* note for dl_buffer_head_sdu_remaining_size_to_send[i] : + * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent + */ + if (UE_template->dl_buffer_info[i] > 0) + LOG_D(MAC, + "[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", + Mod_id, slice_id, frameP, subframeP, UE_id, + i, UE_template->dl_pdus_in_buffer[i], + UE_template->dl_buffer_info[i], + UE_template->dl_buffer_head_sdu_creation_time[i], + UE_template-> + dl_buffer_head_sdu_remaining_size_to_send[i], + UE_template->dl_buffer_head_sdu_is_segmented[i]); #endif - } + } - //#ifdef DEBUG_eNB_SCHEDULER - if ( UE_template->dl_buffer_total>0) - LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n", - Mod_id, frameP, subframeP, UE_id, - UE_template->dl_buffer_total, - UE_template->dl_pdus_total - ); + //#ifdef DEBUG_eNB_SCHEDULER + if (UE_template->dl_buffer_total > 0) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n", + Mod_id, frameP, subframeP, UE_id, + UE_template->dl_buffer_total, + UE_template->dl_pdus_total); - //#endif - } + //#endif + } } // This function returns the estimated number of RBs required by each UE for downlink scheduling -void _assign_rbs_required (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframe, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES], - int min_rb_unit[MAX_NUM_CCs]) +void +_assign_rbs_required(module_id_t Mod_id, + int slice_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t + nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs] + [MAX_NUM_SLICES], int min_rb_unit[MAX_NUM_CCs]) { - rnti_t rnti; - uint16_t TBS = 0; - LTE_eNB_UE_stats *eNB_UE_stats[MAX_NUM_CCs]; - int UE_id,n,i,j,CC_id,pCCid,tmp; - UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; - // UE_TEMPLATE *UE_template; - - // clear rb allocations across all CC_ids - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - pCCid = UE_PCCID(Mod_id,UE_id); - rnti = UE_list->UE_template[pCCid][UE_id].rnti; - - /* skip UE not present in PHY (for any of its active CCs) */ - if (!phy_stats_exist(Mod_id, rnti)) - continue; - - //update CQI information across component carriers - for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti); - eNB_UE_stats[CC_id]->dlsch_mcs1 = cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)]; - } + rnti_t rnti; + uint16_t TBS = 0; + LTE_eNB_UE_stats *eNB_UE_stats[MAX_NUM_CCs]; + int UE_id, n, i, j, CC_id, pCCid, tmp; + UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; + // UE_TEMPLATE *UE_template; - // provide the list of CCs sorted according to MCS - for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) { - for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) { - DevAssert( j < MAX_NUM_CCs ); - - if (eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]]->dlsch_mcs1 > - eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]]->dlsch_mcs1) { - tmp = UE_list->ordered_CCids[i][UE_id]; - UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; - UE_list->ordered_CCids[j][UE_id] = tmp; - } - } - } + // clear rb allocations across all CC_ids + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; + + if (flexran_slice_member(UE_id, slice_id) == 0) + continue; + + pCCid = UE_PCCID(Mod_id, UE_id); + rnti = UE_list->UE_template[pCCid][UE_id].rnti; + + /* skip UE not present in PHY (for any of its active CCs) */ + if (!phy_stats_exist(Mod_id, rnti)) + continue; + + //update CQI information across component carriers + for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { + CC_id = UE_list->ordered_CCids[n][UE_id]; + eNB_UE_stats[CC_id] = + mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti); + eNB_UE_stats[CC_id]->dlsch_mcs1 = + cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)]; + } + + // provide the list of CCs sorted according to MCS + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { + DevAssert(j < MAX_NUM_CCs); + + if (eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]]-> + dlsch_mcs1 > + eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]]-> + dlsch_mcs1) { + tmp = UE_list->ordered_CCids[i][UE_id]; + UE_list->ordered_CCids[i][UE_id] = + UE_list->ordered_CCids[j][UE_id]; + UE_list->ordered_CCids[j][UE_id] = tmp; + } + } + } + + /* NN --> RK + * check the index of UE_template" + */ + if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { + LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); + + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + CC_id = UE_list->ordered_CCids[i][UE_id]; + eNB_UE_stats[CC_id] = + mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti); + + if (cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)] == 0) { //eNB_UE_stats[CC_id]->dlsch_mcs1==0) { + nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small + } else { + nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; + } - /* NN --> RK - * check the index of UE_template" - */ - if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) { - LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id); - - for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti); - - if (cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)] == 0) {//eNB_UE_stats[CC_id]->dlsch_mcs1==0) { - nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small - } else { - nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; - } - - TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]); - nb_rbs_allowed_slice[CC_id][slice_id] = flexran_nb_rbs_allowed_slice(slice_percentage[slice_id], - flexran_get_N_RB_DL(Mod_id, CC_id)); - LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", - UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total, - nb_rbs_required[CC_id][UE_id], flexran_get_ue_wcqi(Mod_id, UE_id), TBS); - - /* calculating required number of RBs for each UE */ - while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; - - if (nb_rbs_required[CC_id][UE_id] > nb_rbs_allowed_slice[CC_id][slice_id]) { - TBS = mac_xface->get_TBS_DL(flexran_get_ue_wcqi(Mod_id, UE_id), nb_rbs_allowed_slice[CC_id][slice_id]); - nb_rbs_required[CC_id][UE_id] = nb_rbs_allowed_slice[CC_id][slice_id]; - break; - } - - TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]); - } // end of while - - LOG_D(MAC,"[eNB %d][SLICE %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - Mod_id, slice_id,frameP,UE_id, CC_id, min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)]); - } + TBS = + mac_xface->get_TBS_DL(cqi_to_mcs + [flexran_get_ue_wcqi + (Mod_id, UE_id)], + nb_rbs_required[CC_id][UE_id]); + nb_rbs_allowed_slice[CC_id][slice_id] = + flexran_nb_rbs_allowed_slice(slice_percentage + [slice_id], + flexran_get_N_RB_DL + (Mod_id, CC_id)); + LOG_D(MAC, + "[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", + UE_id, CC_id, + UE_list->UE_template[pCCid][UE_id].dl_buffer_total, + nb_rbs_required[CC_id][UE_id], + flexran_get_ue_wcqi(Mod_id, UE_id), TBS); + + /* calculating required number of RBs for each UE */ + while (TBS < + UE_list->UE_template[pCCid][UE_id]. + dl_buffer_total) { + nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; + + if (nb_rbs_required[CC_id][UE_id] > + nb_rbs_allowed_slice[CC_id][slice_id]) { + TBS = + mac_xface->get_TBS_DL(flexran_get_ue_wcqi + (Mod_id, UE_id), + nb_rbs_allowed_slice + [CC_id] + [slice_id]); + nb_rbs_required[CC_id][UE_id] = + nb_rbs_allowed_slice[CC_id][slice_id]; + break; + } + + TBS = + mac_xface->get_TBS_DL(cqi_to_mcs + [flexran_get_ue_wcqi + (Mod_id, UE_id)], + nb_rbs_required[CC_id] + [UE_id]); + } // end of while + + LOG_D(MAC, + "[eNB %d][SLICE %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", + Mod_id, slice_id, frameP, UE_id, CC_id, + min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], + TBS, cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)]); + } + } } - } } -void _dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int transmission_mode, - int min_rb_unit, - uint8_t N_RB_DL, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) { - int i; - UE_list_t *UE_list=&eNB_mac_inst[Mod_id].UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for(i=0; i<N_RBG; i++) { - - if((rballoc_sub[CC_id][i] == 0) && - (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) && - (nb_rbs_required_remaining[CC_id][UE_id]>0) && - (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) { - - // if this UE is not scheduled for TM5 - if (ue_sched_ctl->dl_pow_off[CC_id] != 0 ) { - - if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - if (transmission_mode == 5 ) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; - } else { - if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit){ - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - if (transmission_mode == 5 ) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; - } +void +_dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + int transmission_mode, + int min_rb_unit, + uint8_t N_RB_DL, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], unsigned char + MIMO_mode_indicator + [MAX_NUM_CCs][N_RBG_MAX]) +{ + int i; + UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; + UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + + for (i = 0; i < N_RBG; i++) { + + if ((rballoc_sub[CC_id][i] == 0) && + (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) && + (nb_rbs_required_remaining[CC_id][UE_id] > 0) && + (ue_sched_ctl->pre_nb_available_rbs[CC_id] < + nb_rbs_required[CC_id][UE_id])) { + + // if this UE is not scheduled for TM5 + if (ue_sched_ctl->dl_pow_off[CC_id] != 0) { + + if ((i == N_RBG - 1) + && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + MIMO_mode_indicator[CC_id][i] = 1; + if (transmission_mode == 5) { + ue_sched_ctl->dl_pow_off[CC_id] = 1; + } + nb_rbs_required_remaining[CC_id][UE_id] = + nb_rbs_required_remaining[CC_id][UE_id] - + min_rb_unit + 1; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + + min_rb_unit - 1; + } else { + if (nb_rbs_required_remaining[CC_id][UE_id] >= + min_rb_unit) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + MIMO_mode_indicator[CC_id][i] = 1; + if (transmission_mode == 5) { + ue_sched_ctl->dl_pow_off[CC_id] = 1; + } + nb_rbs_required_remaining[CC_id][UE_id] = + nb_rbs_required_remaining[CC_id][UE_id] - + min_rb_unit; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + + min_rb_unit; + } + } + } // dl_pow_off[CC_id][UE_id] ! = 0 } - } // dl_pow_off[CC_id][UE_id] ! = 0 } - } } -void _dlsch_scheduler_pre_processor_reset (int module_idP, - int UE_id, - uint8_t CC_id, - int frameP, - int subframeP, - int N_RBG, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) { - int i,j; - UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map; - int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL/N_RBG; +void +_dlsch_scheduler_pre_processor_reset(int module_idP, + int UE_id, + uint8_t CC_id, + int frameP, + int subframeP, + int N_RBG, + uint16_t nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs][NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_allowed_slice[MAX_NUM_CCs] + [MAX_NUM_SLICES], unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], unsigned char + MIMO_mode_indicator[MAX_NUM_CCs] + [N_RBG_MAX]) +{ + int i, j; + UE_list_t *UE_list = &eNB_mac_inst[module_idP].UE_list; + UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + uint8_t *vrb_map = + eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map; + int RBGsize = + PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL / N_RBG; #ifdef SF05_LIMIT - //int subframe05_limit=0; - int sf05_upper=-1,sf05_lower=-1; + //int subframe05_limit=0; + int sf05_upper = -1, sf05_lower = -1; #endif - // LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti); - - flexran_update_TA(module_idP, UE_id, CC_id); - - if (UE_id==0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); - } - nb_rbs_required[CC_id][UE_id]=0; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; - ue_sched_ctl->dl_pow_off[CC_id] = 2; - nb_rbs_required_remaining[CC_id][UE_id] = 0; - for (i=0; i<n_active_slices;i++) - nb_rbs_allowed_slice[CC_id][i] = 0; -#ifdef SF05_LIMIT - switch (N_RBG) { - case 6: - sf05_lower=0; - sf05_upper=5; - break; - case 8: - sf05_lower=2; - sf05_upper=5; - break; - case 13: - sf05_lower=4; - sf05_upper=7; - break; - case 17: - sf05_lower=7; - sf05_upper=9; - break; - case 25: - sf05_lower=11; - sf05_upper=13; - break; - } + // LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti); + + flexran_update_TA(module_idP, UE_id, CC_id); + + if (UE_id == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME + (VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE, + ue_sched_ctl->ta_update); + } + nb_rbs_required[CC_id][UE_id] = 0; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctl->dl_pow_off[CC_id] = 2; + nb_rbs_required_remaining[CC_id][UE_id] = 0; + for (i = 0; i < n_active_slices; i++) + nb_rbs_allowed_slice[CC_id][i] = 0; +#ifdef SF05_LIMIT + switch (N_RBG) { + case 6: + sf05_lower = 0; + sf05_upper = 5; + break; + case 8: + sf05_lower = 2; + sf05_upper = 5; + break; + case 13: + sf05_lower = 4; + sf05_upper = 7; + break; + case 17: + sf05_lower = 7; + sf05_upper = 9; + break; + case 25: + sf05_lower = 11; + sf05_upper = 13; + break; + } #endif - // Initialize Subbands according to VRB map - for (i=0; i<N_RBG; i++) { - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; - rballoc_sub[CC_id][i] = 0; + // Initialize Subbands according to VRB map + for (i = 0; i < N_RBG; i++) { + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; + rballoc_sub[CC_id][i] = 0; #ifdef SF05_LIMIT - // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors) + // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors) - if ((subframeP==0 || subframeP==5) && - (i>=sf05_lower && i<=sf05_upper)) - rballoc_sub[CC_id][i]=1; + if ((subframeP == 0 || subframeP == 5) && + (i >= sf05_lower && i <= sf05_upper)) + rballoc_sub[CC_id][i] = 1; #endif - // for SI-RNTI,RA-RNTI and P-RNTI allocations - for (j=0;j<RBGsize;j++) { - if (vrb_map[j+(i*RBGsize)]!=0) { - rballoc_sub[CC_id][i] = 1; - LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize)); - break; - } + // for SI-RNTI,RA-RNTI and P-RNTI allocations + for (j = 0; j < RBGsize; j++) { + if (vrb_map[j + (i * RBGsize)] != 0) { + rballoc_sub[CC_id][i] = 1; + LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", + frameP, subframeP, j + (i * RBGsize)); + break; + } + } + LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", + frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); + MIMO_mode_indicator[CC_id][i] = 2; } - LOG_D(MAC,"Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",frameP,subframeP,CC_id,i,rballoc_sub[CC_id][i]); - MIMO_mode_indicator[CC_id][i] = 2; - } } // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done -void _dlsch_scheduler_pre_processor (module_id_t Mod_id, - int slice_id, - frame_t frameP, - sub_frame_t subframeP, - int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag) +void +_dlsch_scheduler_pre_processor(module_id_t Mod_id, + int slice_id, + frame_t frameP, + sub_frame_t subframeP, + int N_RBG[MAX_NUM_CCs], int *mbsfn_flag) { - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], total_ue_count; - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; - int UE_id, i; - uint8_t round = 0; - uint8_t harq_pid = 0; - uint16_t ii,j; - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES]; - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t average_rbs_per_user[MAX_NUM_CCs] = {0}; - rnti_t rnti; - int min_rb_unit[MAX_NUM_CCs]; - uint16_t r1=0; - uint8_t CC_id; - UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; - LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs] = {0}; - - int transmission_mode = 0; - UE_sched_ctrl *ue_sched_ctl; - - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - if (mbsfn_flag[CC_id]>0) // If this CC is allocated for MBSFN skip it here - continue; - - frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id); - - - min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id); - - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) continue; - - UE_id = i; - // Initialize scheduling information for all active UEs - - //if (flexran_slice_member(UE_id, slice_id) == 0) - //continue; - _dlsch_scheduler_pre_processor_reset(Mod_id, - UE_id, - CC_id, - frameP, - subframeP, - N_RBG[CC_id], - nb_rbs_required, - nb_rbs_required_remaining, - nb_rbs_allowed_slice, - rballoc_sub, - MIMO_mode_indicator); + unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], total_ue_count; + unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; + int UE_id, i; + uint8_t round = 0; + uint8_t harq_pid = 0; + uint16_t ii, j; + uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES]; + uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t average_rbs_per_user[MAX_NUM_CCs] = { 0 }; + rnti_t rnti; + int min_rb_unit[MAX_NUM_CCs]; + uint16_t r1 = 0; + uint8_t CC_id; + UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; + LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs] = { 0 }; + + int transmission_mode = 0; + UE_sched_ctrl *ue_sched_ctl; + + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + + if (mbsfn_flag[CC_id] > 0) // If this CC is allocated for MBSFN skip it here + continue; + frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id, CC_id); + + + min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); + + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) + continue; + + UE_id = i; + // Initialize scheduling information for all active UEs + + //if (flexran_slice_member(UE_id, slice_id) == 0) + //continue; + _dlsch_scheduler_pre_processor_reset(Mod_id, + UE_id, + CC_id, + frameP, + subframeP, + N_RBG[CC_id], + nb_rbs_required, + nb_rbs_required_remaining, + nb_rbs_allowed_slice, + rballoc_sub, + MIMO_mode_indicator); + + } } - } - - // Store the DLSCH buffer for each logical channel - _store_dlsch_buffer (Mod_id,slice_id,frameP,subframeP); - - // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - _assign_rbs_required (Mod_id,slice_id, frameP,subframeP,nb_rbs_required,nb_rbs_allowed_slice,min_rb_unit); - - // Sorts the user on the basis of dlsch logical channel buffer and CQI - sort_UEs (Mod_id,frameP,subframeP); - - total_ue_count = 0; - - // loop over all active UEs - for (i=UE_list->head; i>=0; i=UE_list->next[i]) { - rnti = flexran_get_ue_crnti(Mod_id, i); - if(rnti == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - UE_id = i; - - if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - if (!phy_stats_exist(Mod_id, rnti)) - continue; - - for (ii=0; ii < UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice[CC_id][slice_id]; - flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round); - - // if there is no available harq_process, skip the UE - if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0) - continue; - - average_rbs_per_user[CC_id]=0; - - frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id); - - // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0); - - if(round>0) { - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - } - - //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id]; - if (nb_rbs_required[CC_id][UE_id] > 0) { - total_ue_count = total_ue_count + 1; - } - - - // hypotetical assignement - /* - * If schedule is enabled and if the priority of the UEs is modified - * The average rbs per logical channel per user will depend on the level of - * priority. Concerning the hypothetical assignement, we should assign more - * rbs to prioritized users. Maybe, we can do a mapping between the - * average rbs per user and the level of priority or multiply the average rbs - * per user by a coefficient which represents the degree of priority. - */ - - if (total_ue_count == 0) { - average_rbs_per_user[CC_id] = 0; - } else if( (min_rb_unit[CC_id] * total_ue_count) <= nb_rbs_allowed_slice[CC_id][slice_id] ) { - average_rbs_per_user[CC_id] = (uint16_t) floor(nb_rbs_allowed_slice[CC_id][slice_id]/total_ue_count); - } else { - average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE - } - } - } - - // note: nb_rbs_required is assigned according to total_buffer_dl - // extend nb_rbs_required to capture per LCID RB required - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - rnti = UE_RNTI(Mod_id,i); - - if(rnti == NOT_A_RNTI) - continue; - - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - if (!phy_stats_exist(Mod_id, rnti)) - continue; - - if (flexran_slice_member(i, slice_id) == 0) - continue; - - for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) { - CC_id = UE_list->ordered_CCids[ii][i]; - - // control channel - if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) { - nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i]; - } else { - nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]); - - } + + // Store the DLSCH buffer for each logical channel + _store_dlsch_buffer(Mod_id, slice_id, frameP, subframeP); + + // Calculate the number of RBs required by each UE on the basis of logical channel's buffer + _assign_rbs_required(Mod_id, slice_id, frameP, subframeP, + nb_rbs_required, nb_rbs_allowed_slice, + min_rb_unit); + + // Sorts the user on the basis of dlsch logical channel buffer and CQI + sort_UEs(Mod_id, frameP, subframeP); + + total_ue_count = 0; + + // loop over all active UEs + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + rnti = flexran_get_ue_crnti(Mod_id, i); + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + + UE_id = i; + + if (flexran_slice_member(UE_id, slice_id) == 0) + continue; + + if (!phy_stats_exist(Mod_id, rnti)) + continue; + + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl->max_allowed_rbs[CC_id] = + nb_rbs_allowed_slice[CC_id][slice_id]; + flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, + &harq_pid, &round); + + // if there is no available harq_process, skip the UE + if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id] < 0) + continue; + + average_rbs_per_user[CC_id] = 0; + + frame_parms[CC_id] = + mac_xface->get_lte_frame_parms(Mod_id, CC_id); + + // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0); + + if (round > 0) { + nb_rbs_required[CC_id][UE_id] = + UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + } + //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id]; + if (nb_rbs_required[CC_id][UE_id] > 0) { + total_ue_count = total_ue_count + 1; + } + // hypotetical assignement + /* + * If schedule is enabled and if the priority of the UEs is modified + * The average rbs per logical channel per user will depend on the level of + * priority. Concerning the hypothetical assignement, we should assign more + * rbs to prioritized users. Maybe, we can do a mapping between the + * average rbs per user and the level of priority or multiply the average rbs + * per user by a coefficient which represents the degree of priority. + */ + + if (total_ue_count == 0) { + average_rbs_per_user[CC_id] = 0; + } else if ((min_rb_unit[CC_id] * total_ue_count) <= + nb_rbs_allowed_slice[CC_id][slice_id]) { + average_rbs_per_user[CC_id] = + (uint16_t) floor(nb_rbs_allowed_slice[CC_id][slice_id] + / total_ue_count); + } else { + average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE + } + } } - } - - //Allocation to UEs is done in 2 rounds, - // 1st stage: average number of RBs allocated to each UE - // 2nd stage: remaining RBs are allocated to high priority UEs - for(r1=0; r1<2; r1++) { - - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - - if (flexran_slice_member(i, slice_id) == 0) - continue; - - for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) { - CC_id = UE_list->ordered_CCids[ii][i]; - - if(r1 == 0) { - nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i]; - } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round - nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i]; - } - - if (nb_rbs_required[CC_id][i]> 0 ) - LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", - r1, CC_id, i, - nb_rbs_required_remaining[CC_id][i], - nb_rbs_required_remaining_1[CC_id][i], - nb_rbs_required[CC_id][i], - UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); - - } + + // note: nb_rbs_required is assigned according to total_buffer_dl + // extend nb_rbs_required to capture per LCID RB required + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + rnti = UE_RNTI(Mod_id, i); + + if (rnti == NOT_A_RNTI) + continue; + + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + + if (!phy_stats_exist(Mod_id, rnti)) + continue; + + if (flexran_slice_member(i, slice_id) == 0) + continue; + + for (ii = 0; ii < UE_num_active_CC(UE_list, i); ii++) { + CC_id = UE_list->ordered_CCids[ii][i]; + + // control channel + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED) { + nb_rbs_required_remaining_1[CC_id][i] = + nb_rbs_required[CC_id][i]; + } else { + nb_rbs_required_remaining_1[CC_id][i] = + cmin(average_rbs_per_user[CC_id], + nb_rbs_required[CC_id][i]); + + } + } } - if (total_ue_count > 0 ) { - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - UE_id = i; - + //Allocation to UEs is done in 2 rounds, + // 1st stage: average number of RBs allocated to each UE + // 2nd stage: remaining RBs are allocated to high priority UEs + for (r1 = 0; r1 < 2; r1++) { + + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + + if (flexran_slice_member(i, slice_id) == 0) + continue; + + for (ii = 0; ii < UE_num_active_CC(UE_list, i); ii++) { + CC_id = UE_list->ordered_CCids[ii][i]; + + if (r1 == 0) { + nb_rbs_required_remaining[CC_id][i] = + nb_rbs_required_remaining_1[CC_id][i]; + } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round + nb_rbs_required_remaining[CC_id][i] = + nb_rbs_required[CC_id][i] - + nb_rbs_required_remaining_1[CC_id][i] + + nb_rbs_required_remaining[CC_id][i]; + } + + if (nb_rbs_required[CC_id][i] > 0) + LOG_D(MAC, + "round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", + r1, CC_id, i, + nb_rbs_required_remaining[CC_id][i], + nb_rbs_required_remaining_1[CC_id][i], + nb_rbs_required[CC_id][i], + UE_list->UE_sched_ctrl[i]. + pre_nb_available_rbs[CC_id], N_RBG[CC_id], + min_rb_unit[CC_id]); + + } + } + + if (total_ue_count > 0) { + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + UE_id = i; + + if (flexran_slice_member(UE_id, slice_id) == 0) + continue; + + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + flexran_get_harq(Mod_id, CC_id, UE_id, frameP, + subframeP, &harq_pid, &round); + rnti = UE_RNTI(Mod_id, UE_id); + + // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti ); + if (rnti == NOT_A_RNTI) + continue; + + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + continue; + + if (!phy_stats_exist(Mod_id, rnti)) + continue; + + transmission_mode = + mac_xface->get_transmission_mode(Mod_id, CC_id, + rnti); + //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti); + /* 1st allocate for the retx */ + + // retransmission in data channels + // control channel in the 1st transmission + // data channel for all TM + LOG_T(MAC, + "calling dlsch_scheduler_pre_processor_allocate .. \n "); + _dlsch_scheduler_pre_processor_allocate(Mod_id, UE_id, + CC_id, + N_RBG[CC_id], + transmission_mode, + min_rb_unit + [CC_id], + frame_parms + [CC_id]-> + N_RB_DL, + nb_rbs_required, + nb_rbs_required_remaining, + rballoc_sub, + MIMO_mode_indicator); + } + } + } // total_ue_count + } // end of for for r1 and r2 + + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + UE_id = i; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round); - rnti = UE_RNTI(Mod_id,UE_id); - - // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti ); - if(rnti == NOT_A_RNTI) - continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - if (!phy_stats_exist(Mod_id, rnti)) - continue; - - transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti); - //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti); - /* 1st allocate for the retx */ - - // retransmission in data channels - // control channel in the 1st transmission - // data channel for all TM - LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); - _dlsch_scheduler_pre_processor_allocate (Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - transmission_mode, - min_rb_unit[CC_id], - frame_parms[CC_id]->N_RB_DL, - nb_rbs_required, - nb_rbs_required_remaining, - rballoc_sub, - MIMO_mode_indicator); - } - } - } // total_ue_count - } // end of for for r1 and r2 - - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - UE_id = i; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) { - LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id); - LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]); - LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id); - - for(j=0; j<N_RBG[CC_id]; j++) { - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i]; - LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]); - } - - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; - LOG_D(MAC,"[eNB %d][SLICE %d] Total RBs allocated for UE%d = %d\n", - Mod_id, slice_id, UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]); - } + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; + + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { + LOG_D(MAC, + "******************DL Scheduling Information for UE%d ************************\n", + UE_id); + LOG_D(MAC, "dl power offset UE%d = %d \n", UE_id, + ue_sched_ctl->dl_pow_off[CC_id]); + LOG_D(MAC, + "***********RB Alloc for every subband for UE%d ***********\n", + UE_id); + + for (j = 0; j < N_RBG[CC_id]; j++) { + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i]; + LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n", + UE_id, j, + ue_sched_ctl->rballoc_sub_UE[CC_id][j]); + } + + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; + LOG_D(MAC, + "[eNB %d][SLICE %d] Total RBs allocated for UE%d = %d\n", + Mod_id, slice_id, UE_id, + ue_sched_ctl->pre_nb_available_rbs[CC_id]); + } + } } - } } #define SF05_LIMIT 1 @@ -714,956 +826,1180 @@ void _dlsch_scheduler_pre_processor (module_id_t Mod_id, */ void -flexran_schedule_ue_spec_default(mid_t mod_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) +flexran_schedule_ue_spec_default(mid_t mod_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) //------------------------------------------------------------------------------ { - int i=0; - - flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); - - for (i = 0; i < n_active_slices; i++) { - - // Load any updated functions - if (update_dl_scheduler[i] > 0 ) { - slice_sched[i] = dlsym(NULL, dl_scheduler_type[i]); - update_dl_scheduler[i] = 0; - update_dl_scheduler_current[i] = 0; - slice_percentage_current[i]= slice_percentage[i]; - total_slice_percentage+=slice_percentage[i]; - LOG_N(MAC,"update dl scheduler slice %d\n", i); - } - - // check if the number of slices has changed, and log - if (n_active_slices_current != n_active_slices ){ - if ((n_active_slices > 0) && (n_active_slices <= MAX_NUM_SLICES)) { - LOG_N(MAC,"[eNB %d]frame %d subframe %d: number of active slices has changed: %d-->%d\n", - mod_id, frame, subframe, n_active_slices_current, n_active_slices); - n_active_slices_current = n_active_slices; - } else { - LOG_W(MAC,"invalid number of slices %d, revert to the previous value %d\n",n_active_slices, n_active_slices_current); - n_active_slices = n_active_slices_current; - } - } - - // check if the slice rb share has changed, and log the console - if (slice_percentage_current[i] != slice_percentage[i]){ - if ((slice_percentage[i] >= 0.0) && (slice_percentage[i] <= 1.0)){ - if ((total_slice_percentage - slice_percentage_current[i] + slice_percentage[i]) <= 1.0) { - total_slice_percentage=total_slice_percentage - slice_percentage_current[i] + slice_percentage[i]; - LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: total percentage %f, slice RB percentage has changed: %f-->%f\n", - mod_id, i, frame, subframe, total_slice_percentage, slice_percentage_current[i], slice_percentage[i]); - slice_percentage_current[i] = slice_percentage[i]; - } else { - LOG_W(MAC,"[eNB %d][SLICE %d] invalid total RB share (%f->%f), revert the previous value (%f->%f)\n", - mod_id,i, - total_slice_percentage, - total_slice_percentage - slice_percentage_current[i] + slice_percentage[i], - slice_percentage[i],slice_percentage_current[i]); - slice_percentage[i]= slice_percentage_current[i]; + int i = 0; + + flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); + for (i = 0; i < n_active_slices; i++) { + + // Load any updated functions + if (update_dl_scheduler[i] > 0) { + slice_sched[i] = dlsym(NULL, dl_scheduler_type[i]); + update_dl_scheduler[i] = 0; + update_dl_scheduler_current[i] = 0; + slice_percentage_current[i] = slice_percentage[i]; + total_slice_percentage += slice_percentage[i]; + LOG_N(MAC, "update dl scheduler slice %d\n", i); } - } else { - LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice RB share, revert the previous value (%f->%f)\n",mod_id, i, slice_percentage[i],slice_percentage_current[i]); - slice_percentage[i]= slice_percentage_current[i]; + // check if the number of slices has changed, and log + if (n_active_slices_current != n_active_slices) { + if ((n_active_slices > 0) + && (n_active_slices <= MAX_NUM_SLICES)) { + LOG_N(MAC, + "[eNB %d]frame %d subframe %d: number of active slices has changed: %d-->%d\n", + mod_id, frame, subframe, n_active_slices_current, + n_active_slices); + n_active_slices_current = n_active_slices; + } else { + LOG_W(MAC, + "invalid number of slices %d, revert to the previous value %d\n", + n_active_slices, n_active_slices_current); + n_active_slices = n_active_slices_current; + } + } + // check if the slice rb share has changed, and log the console + if (slice_percentage_current[i] != slice_percentage[i]) { + if ((slice_percentage[i] >= 0.0) + && (slice_percentage[i] <= 1.0)) { + if ((total_slice_percentage - slice_percentage_current[i] + + slice_percentage[i]) <= 1.0) { + total_slice_percentage = + total_slice_percentage - + slice_percentage_current[i] + slice_percentage[i]; + LOG_N(MAC, + "[eNB %d][SLICE %d] frame %d subframe %d: total percentage %f, slice RB percentage has changed: %f-->%f\n", + mod_id, i, frame, subframe, + total_slice_percentage, + slice_percentage_current[i], + slice_percentage[i]); + slice_percentage_current[i] = slice_percentage[i]; + } else { + LOG_W(MAC, + "[eNB %d][SLICE %d] invalid total RB share (%f->%f), revert the previous value (%f->%f)\n", + mod_id, i, total_slice_percentage, + total_slice_percentage - + slice_percentage_current[i] + + slice_percentage[i], slice_percentage[i], + slice_percentage_current[i]); + slice_percentage[i] = slice_percentage_current[i]; - } - } - - // check if the slice max MCS, and log the console - if (slice_maxmcs_current[i] != slice_maxmcs[i]){ - if ((slice_maxmcs[i] >= 0) && (slice_maxmcs[i] < 29)){ - LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n", - mod_id, i, frame, subframe, slice_maxmcs_current[i], slice_maxmcs[i]); - slice_maxmcs_current[i] = slice_maxmcs[i]; - } else { - LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice max mcs %d, revert the previous value %d\n",mod_id, i, slice_percentage[i],slice_percentage[i]); - slice_maxmcs[i]= slice_maxmcs_current[i]; - } - } - - // check if a new scheduler, and log the console - if (update_dl_scheduler_current[i] != update_dl_scheduler[i]){ - LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: DL scheduler for this slice is updated: %s \n", - mod_id, i, frame, subframe, dl_scheduler_type[i]); - update_dl_scheduler_current[i] = update_dl_scheduler[i]; - } + } + } else { + LOG_W(MAC, + "[eNB %d][SLICE %d] invalid slice RB share, revert the previous value (%f->%f)\n", + mod_id, i, slice_percentage[i], + slice_percentage_current[i]); + slice_percentage[i] = slice_percentage_current[i]; - // Run each enabled slice-specific schedulers one by one - //LOG_N(MAC,"[eNB %d]frame %d subframe %d slice %d: calling the scheduler\n", mod_id, frame, subframe,i); - slice_sched[i](mod_id, i, frame, subframe, mbsfn_flag,dl_info); + } + } + // check if the slice max MCS, and log the console + if (slice_maxmcs_current[i] != slice_maxmcs[i]) { + if ((slice_maxmcs[i] >= 0) && (slice_maxmcs[i] < 29)) { + LOG_N(MAC, + "[eNB %d][SLICE %d] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n", + mod_id, i, frame, subframe, slice_maxmcs_current[i], + slice_maxmcs[i]); + slice_maxmcs_current[i] = slice_maxmcs[i]; + } else { + LOG_W(MAC, + "[eNB %d][SLICE %d] invalid slice max mcs %d, revert the previous value %d\n", + mod_id, i, slice_percentage[i], slice_percentage[i]); + slice_maxmcs[i] = slice_maxmcs_current[i]; + } + } + // check if a new scheduler, and log the console + if (update_dl_scheduler_current[i] != update_dl_scheduler[i]) { + LOG_N(MAC, + "[eNB %d][SLICE %d] frame %d subframe %d: DL scheduler for this slice is updated: %s \n", + mod_id, i, frame, subframe, dl_scheduler_type[i]); + update_dl_scheduler_current[i] = update_dl_scheduler[i]; + } + // Run each enabled slice-specific schedulers one by one + //LOG_N(MAC,"[eNB %d]frame %d subframe %d slice %d: calling the scheduler\n", mod_id, frame, subframe,i); + slice_sched[i] (mod_id, i, frame, subframe, mbsfn_flag, dl_info); + + } - } - } -uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs){ - return (uint16_t) floor(rb_percentage * total_rbs); +uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs) +{ + return (uint16_t) floor(rb_percentage * total_rbs); } -int flexran_slice_maxmcs(int slice_id) { - return slice_maxmcs[slice_id]; +int flexran_slice_maxmcs(int slice_id) +{ + return slice_maxmcs[slice_id]; } -int flexran_slice_member(int UE_id, int slice_id){ - // group membership definition - int slice_member = 0 ; - - if ((slice_id < 0) || (slice_id > n_active_slices)) - LOG_W(MAC,"out of range slice id %d\n",slice_id); - - switch (slicing_strategy) { - case SLICE_MASK: - switch (slice_id){ - case 0: - if (SLICE0_MASK&UE_id){ - slice_member=1; - } - break; - case 1: - if (SLICE1_MASK&UE_id){ - slice_member=1; - } - break; - case 2: - if (SLICE2_MASK&UE_id){ - slice_member=1; - } - break; - case 3: - if (SLICE3_MASK&UE_id){ - slice_member=1; - } - break; - default : - LOG_W(MAC,"unknown slice_id %d\n", slice_id); - break; - - } - break; - case UEID_TO_SLICEID: - default: - if ((UE_id % n_active_slices) == slice_id){ - slice_member= 1; // this ue is a member of this slice +int flexran_slice_member(int UE_id, int slice_id) +{ + // group membership definition + int slice_member = 0; + + if ((slice_id < 0) || (slice_id > n_active_slices)) + LOG_W(MAC, "out of range slice id %d\n", slice_id); + + switch (slicing_strategy) { + case SLICE_MASK: + switch (slice_id) { + case 0: + if (SLICE0_MASK & UE_id) { + slice_member = 1; + } + break; + case 1: + if (SLICE1_MASK & UE_id) { + slice_member = 1; + } + break; + case 2: + if (SLICE2_MASK & UE_id) { + slice_member = 1; + } + break; + case 3: + if (SLICE3_MASK & UE_id) { + slice_member = 1; + } + break; + default: + LOG_W(MAC, "unknown slice_id %d\n", slice_id); + break; + + } + break; + case UEID_TO_SLICEID: + default: + if ((UE_id % n_active_slices) == slice_id) { + slice_member = 1; // this ue is a member of this slice + } + break; } - break; - } - - return slice_member; + + return slice_member; } + /* more aggressive rb and mcs allocation with medium priority and the traffic qci */ void -flexran_schedule_ue_spec_embb(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) - +flexran_schedule_ue_spec_embb(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) { - flexran_schedule_ue_spec_common(mod_id, - slice_id, - frame, - subframe, - mbsfn_flag, - dl_info); - + flexran_schedule_ue_spec_common(mod_id, + slice_id, + frame, subframe, mbsfn_flag, dl_info); + } + /* more conservative mcs allocation with high priority and the traffic qci */ void -flexran_schedule_ue_spec_urllc(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) - +flexran_schedule_ue_spec_urllc(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) { - flexran_schedule_ue_spec_common(mod_id, - slice_id, - frame, - subframe, - mbsfn_flag, - dl_info); - + flexran_schedule_ue_spec_common(mod_id, + slice_id, + frame, subframe, mbsfn_flag, dl_info); + } + /* constant rb allocation with low mcs with low priority and given the UE capabilities */ void -flexran_schedule_ue_spec_mmtc(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) - +flexran_schedule_ue_spec_mmtc(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) { - - flexran_schedule_ue_spec_common(mod_id, - slice_id, - frame, - subframe, - mbsfn_flag, - dl_info); - + + flexran_schedule_ue_spec_common(mod_id, + slice_id, + frame, subframe, mbsfn_flag, dl_info); + } + /* regular rb and mcs allocation with low priority */ void -flexran_schedule_ue_spec_be(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) - +flexran_schedule_ue_spec_be(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) { - - flexran_schedule_ue_spec_common(mod_id, - slice_id, - frame, - subframe, - mbsfn_flag, - dl_info); - + + flexran_schedule_ue_spec_common(mod_id, + slice_id, + frame, subframe, mbsfn_flag, dl_info); + } //------------------------------------------------------------------------------ void -flexran_schedule_ue_spec_common(mid_t mod_id, - int slice_id, - uint32_t frame, - uint32_t subframe, - int *mbsfn_flag, - Protocol__FlexranMessage **dl_info) +flexran_schedule_ue_spec_common(mid_t mod_id, + int slice_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) //------------------------------------------------------------------------------ { - uint8_t CC_id; - int UE_id; - int N_RBG[MAX_NUM_CCs]; - unsigned char aggregation; - mac_rlc_status_resp_t rlc_status; - unsigned char header_len = 0, header_len_last = 0, ta_len = 0; - uint16_t nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb; - uint16_t TBS, j, rnti; - uint8_t round = 0; - uint8_t harq_pid = 0; - uint16_t sdu_length_total = 0; - int mcs, mcs_tmp; - uint16_t min_rb_unit[MAX_NUM_CCs]; - eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; - /* TODO: Must move the helper structs to scheduler implementation */ - UE_list_t *UE_list = &eNB->UE_list; - int32_t normalized_rx_power, target_rx_power; - int32_t tpc = 1; - static int32_t tpc_accumulated=0; - UE_sched_ctrl *ue_sched_ctl; - LTE_eNB_UE_stats *eNB_UE_stats = NULL; - Protocol__FlexDlData *dl_data[NUM_MAX_UE]; - int num_ues_added = 0; - int channels_added = 0; - - Protocol__FlexDlDci *dl_dci; - Protocol__FlexRlcPdu *rlc_pdus[11]; - uint32_t ce_flags = 0; - - uint8_t rballoc_sub[25]; - int i; - uint32_t data_to_request; - uint32_t dci_tbs; - uint8_t ue_has_transmission = 0; - uint32_t ndi; - + uint8_t CC_id; + int UE_id; + int N_RBG[MAX_NUM_CCs]; + unsigned char aggregation; + mac_rlc_status_resp_t rlc_status; + unsigned char header_len = 0, header_len_last = 0, ta_len = 0; + uint16_t nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], + nb_available_rb; + uint16_t TBS, j, rnti; + uint8_t round = 0; + uint8_t harq_pid = 0; + uint16_t sdu_length_total = 0; + int mcs, mcs_tmp; + uint16_t min_rb_unit[MAX_NUM_CCs]; + eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; + /* TODO: Must move the helper structs to scheduler implementation */ + UE_list_t *UE_list = &eNB->UE_list; + int32_t normalized_rx_power, target_rx_power; + int32_t tpc = 1; + static int32_t tpc_accumulated = 0; + UE_sched_ctrl *ue_sched_ctl; + LTE_eNB_UE_stats *eNB_UE_stats = NULL; + Protocol__FlexDlData *dl_data[NUM_MAX_UE]; + int num_ues_added = 0; + int channels_added = 0; + + Protocol__FlexDlDci *dl_dci; + Protocol__FlexRlcPdu *rlc_pdus[11]; + uint32_t ce_flags = 0; + + uint8_t rballoc_sub[25]; + int i; + uint32_t data_to_request; + uint32_t dci_tbs; + uint8_t ue_has_transmission = 0; + uint32_t ndi; + #if 0 - - if (UE_list->head==-1) { - return; - } - + + if (UE_list->head == -1) { + return; + } #endif - start_meas(&eNB->schedule_dlsch); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN); - - //weight = get_ue_weight(module_idP,UE_id); - aggregation = 1; // set to the maximum aggregation level - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - min_rb_unit[CC_id] = get_min_rb_unit(mod_id, CC_id); - // get number of PRBs less those used by common channels - total_nb_available_rb[CC_id] = flexran_get_N_RB_DL(mod_id, CC_id); - for (i=0;i < flexran_get_N_RB_DL(mod_id, CC_id); i++) - if (eNB->common_channels[CC_id].vrb_map[i] != 0) - total_nb_available_rb[CC_id]--; - - N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id); - - // store the global enb stats: - eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; - eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].dlsch_bytes_tx=0; - eNB->eNB_stats[CC_id].dlsch_pdus_tx=0; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN); - - start_meas(&eNB->schedule_dlsch_preprocessor); - _dlsch_scheduler_pre_processor(mod_id, - slice_id, - frame, - subframe, - N_RBG, - mbsfn_flag); - stop_meas(&eNB->schedule_dlsch_preprocessor); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT); - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id); - - if (mbsfn_flag[CC_id]>0) - continue; - - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - - rnti = flexran_get_ue_crnti(mod_id, UE_id); - eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti); - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - if (eNB_UE_stats==NULL) { - LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n"); - // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); - continue; - } - - if (flexran_slice_member(UE_id, slice_id) == 0) - continue; - - if (rnti==NOT_A_RNTI) { - LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id,UE_list->num_UEs); - // mac_xface->macphy_exit("Cannot find rnti for UE_id"); - continue; - } - - switch(mac_xface->get_transmission_mode(mod_id,CC_id,rnti)){ - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(mod_id,CC_id), - eNB_UE_stats->DL_cqi[0], - format1); - break; - case 3: - aggregation = get_aggregation(get_bw_index(mod_id,CC_id), - eNB_UE_stats->DL_cqi[0], - format2A); - break; - default: - LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(mod_id,CC_id,rnti)); - aggregation = 2; - } - - if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated - CCE_allocation_infeasible(mod_id, CC_id, 0, subframe, aggregation, rnti)) { - LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - mod_id, frame, UE_id, CC_id); - //if(mac_xface->get_transmission_mode(module_idP,rnti)==5) - continue; //to next user (there might be rbs availiable for other UEs in TM5 - // else - // break; - } - - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - set_ue_dai (subframe, - flexran_get_subframe_assignment(mod_id, CC_id), - UE_id, - CC_id, - UE_list); - //TODO: update UL DAI after DLSCH scheduling - //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe,frame_parms); - } - - channels_added = 0; - - // After this point all the UEs will be scheduled - dl_data[num_ues_added] = (Protocol__FlexDlData *) malloc(sizeof(Protocol__FlexDlData)); - protocol__flex_dl_data__init(dl_data[num_ues_added]); - dl_data[num_ues_added]->has_rnti = 1; - dl_data[num_ues_added]->rnti = rnti; - dl_data[num_ues_added]->n_rlc_pdu = 0; - dl_data[num_ues_added]->has_serv_cell_index = 1; - dl_data[num_ues_added]->serv_cell_index = CC_id; - - nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; - flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round); - sdu_length_total=0; - mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)]; - // LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs); - mcs = cmin(mcs,flexran_slice_maxmcs(slice_id)); -#ifdef EXMIMO + start_meas(&eNB->schedule_dlsch); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); + + //weight = get_ue_weight(module_idP,UE_id); + aggregation = 1; // set to the maximum aggregation level + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + min_rb_unit[CC_id] = get_min_rb_unit(mod_id, CC_id); + // get number of PRBs less those used by common channels + total_nb_available_rb[CC_id] = flexran_get_N_RB_DL(mod_id, CC_id); + for (i = 0; i < flexran_get_N_RB_DL(mod_id, CC_id); i++) + if (eNB->common_channels[CC_id].vrb_map[i] != 0) + total_nb_available_rb[CC_id]--; + + N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id); + + // store the global enb stats: + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].available_prbs = + total_nb_available_rb[CC_id]; + eNB->eNB_stats[CC_id].total_available_prbs += + total_nb_available_rb[CC_id]; + eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; + eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); - if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) { - mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)]; - mcs = cmin(mcs,16); - } + start_meas(&eNB->schedule_dlsch_preprocessor); + _dlsch_scheduler_pre_processor(mod_id, + slice_id, + frame, subframe, N_RBG, mbsfn_flag); + stop_meas(&eNB->schedule_dlsch_preprocessor); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id); + + if (mbsfn_flag[CC_id] > 0) + continue; + + for (UE_id = UE_list->head; UE_id >= 0; + UE_id = UE_list->next[UE_id]) { + + rnti = flexran_get_ue_crnti(mod_id, UE_id); + eNB_UE_stats = + mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti); + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + + if (eNB_UE_stats == NULL) { + LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); + // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); + continue; + } + + if (flexran_slice_member(UE_id, slice_id) == 0) + continue; + + if (rnti == NOT_A_RNTI) { + LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", + UE_id, UE_list->num_UEs); + // mac_xface->macphy_exit("Cannot find rnti for UE_id"); + continue; + } + + switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(mod_id, CC_id), + eNB_UE_stats->DL_cqi[0], + format1); + break; + case 3: + aggregation = get_aggregation(get_bw_index(mod_id, CC_id), + eNB_UE_stats->DL_cqi[0], + format2A); + break; + default: + LOG_W(MAC, "Unsupported transmission mode %d\n", + mac_xface->get_transmission_mode(mod_id, CC_id, + rnti)); + aggregation = 2; + } + + if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated + CCE_allocation_infeasible(mod_id, CC_id, 0, subframe, + aggregation, rnti)) { + LOG_D(MAC, + "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", + mod_id, frame, UE_id, CC_id); + //if(mac_xface->get_transmission_mode(module_idP,rnti)==5) + continue; //to next user (there might be rbs availiable for other UEs in TM5 + // else + // break; + } + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + set_ue_dai(subframe, + flexran_get_subframe_assignment(mod_id, CC_id), + UE_id, CC_id, UE_list); + //TODO: update UL DAI after DLSCH scheduling + //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe,frame_parms); + } + + channels_added = 0; + + // After this point all the UEs will be scheduled + dl_data[num_ues_added] = + (Protocol__FlexDlData *) + malloc(sizeof(Protocol__FlexDlData)); + protocol__flex_dl_data__init(dl_data[num_ues_added]); + dl_data[num_ues_added]->has_rnti = 1; + dl_data[num_ues_added]->rnti = rnti; + dl_data[num_ues_added]->n_rlc_pdu = 0; + dl_data[num_ues_added]->has_serv_cell_index = 1; + dl_data[num_ues_added]->serv_cell_index = CC_id; + + nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; + flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, + &harq_pid, &round); + sdu_length_total = 0; + mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)]; + // LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs); + mcs = cmin(mcs, flexran_slice_maxmcs(slice_id)); +#ifdef EXMIMO + + if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) { + mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)]; + mcs = cmin(mcs, 16); + } #endif - // initializing the rb allocation indicator for each UE - for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; - rballoc_sub[j] = 0; - } - - /* LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", */ - /* mod_id, frame, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, */ - /* eNB_UE_stats->DL_cqi[0], mcs, */ - /* UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); */ - - dl_dci = (Protocol__FlexDlDci*) malloc(sizeof(Protocol__FlexDlDci)); - protocol__flex_dl_dci__init(dl_dci); - dl_data[num_ues_added]->dl_dci = dl_dci; - - - dl_dci->has_rnti = 1; - dl_dci->rnti = rnti; - dl_dci->has_harq_process = 1; - dl_dci->harq_process = harq_pid; - - /* process retransmission */ - if (round > 0) { - - LOG_D(FLEXRAN_AGENT, "There was a retransmission just now and the round was %d\n", round); - - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI); - LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id, subframe,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); - } + // initializing the rb allocation indicator for each UE + for (j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] + = 0; + rballoc_sub[j] = 0; + } - mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid]; - - // get freq_allocation - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - - /*TODO: Must add this to FlexRAN agent API */ - dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb); - - if (nb_rb <= nb_available_rb) { - - if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { - for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) { - if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - - if((j == flexran_get_N_RBG(mod_id, CC_id) - 1) && - ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)|| - (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1; + /* LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", */ + /* mod_id, frame, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, */ + /* eNB_UE_stats->DL_cqi[0], mcs, */ + /* UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); */ + + dl_dci = + (Protocol__FlexDlDci *) + malloc(sizeof(Protocol__FlexDlDci)); + protocol__flex_dl_dci__init(dl_dci); + dl_data[num_ues_added]->dl_dci = dl_dci; + + + dl_dci->has_rnti = 1; + dl_dci->rnti = rnti; + dl_dci->has_harq_process = 1; + dl_dci->harq_process = harq_pid; + + /* process retransmission */ + if (round > 0) { + + LOG_D(FLEXRAN_AGENT, + "There was a retransmission just now and the round was %d\n", + round); + + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + UE_list->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(mod_id, CC_id, rnti, + UE_list->UE_template[CC_id][UE_id].DAI); + LOG_D(MAC, + "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", + CC_id, subframe, UE_id, + UE_list->UE_template[CC_id][UE_id].DAI); + } + + mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid]; + + // get freq_allocation + nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + + /*TODO: Must add this to FlexRAN agent API */ + dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb); + + if (nb_rb <= nb_available_rb) { + + if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band + UE_list->UE_template[CC_id][UE_id]. + rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + + while ((nb_rb_temp > 0) + && (j < flexran_get_N_RBG(mod_id, CC_id))) { + if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == + 1) { + UE_list-> + UE_template[CC_id] + [UE_id].rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + + if ((j == + flexran_get_N_RBG(mod_id, CC_id) - 1) + && + ((flexran_get_N_RB_DL(mod_id, CC_id) == + 25) + || (flexran_get_N_RB_DL(mod_id, CC_id) + == 50))) { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id] + + 1; + } else { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id]; + } + } + j = j + 1; + } + } + + nb_available_rb -= nb_rb; + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].dl_pow_off = + ue_sched_ctl->dl_pow_off[CC_id]; + + for (j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].rballoc_sub[j] = + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband + [harq_pid][j]; + rballoc_sub[j] = + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband + [harq_pid][j]; + } + + // Keep the old NDI, do not toggle + ndi = + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + tpc = + UE_list->UE_template[CC_id][UE_id]. + oldTPC[harq_pid]; + UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs; + + ue_has_transmission = 1; + num_ues_added++; } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; + LOG_D(MAC, + "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + mod_id, frame, CC_id, UE_id); + ue_has_transmission = 0; + } + //End of retransmission + } else { /* This is a potentially new SDU opportunity */ + 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(mcs, nb_available_rb); + dci_tbs = TBS; + LOG_D(FLEXRAN_AGENT, "TBS is %d\n", TBS); + + // check first for RLC data on DCCH + // add the length for all the control elements (timing adv, drx, etc) : header + payload + + ta_len = (ue_sched_ctl->ta_update != 0) ? 2 : 0; + + dl_data[num_ues_added]->n_ce_bitmap = 2; + dl_data[num_ues_added]->ce_bitmap = + (uint32_t *) calloc(2, sizeof(uint32_t)); + + if (ta_len > 0) { + ce_flags |= PROTOCOL__FLEX_CE_TYPE__FLPCET_TA; + } + + /*TODO: Add other flags if DRX and other CE are required */ + + // Add the control element flags to the flexran message + dl_data[num_ues_added]->ce_bitmap[0] = ce_flags; + dl_data[num_ues_added]->ce_bitmap[1] = ce_flags; + + // TODO : Need to prioritize DRBs + // Loop through the UE logical channels (DCCH, DCCH1, DTCH for now) + header_len = 0; + header_len_last = 0; + sdu_length_total = 0; + for (j = 1; j < NB_RB_MAX; j++) { + header_len += 3; + // Need to see if we have space for data from this channel + if (dci_tbs - ta_len - header_len - sdu_length_total > + 0) { + LOG_D(MAC, + "[TEST]Requested %d bytes from RLC buffer on channel %d during first call\n", + dci_tbs - ta_len - header_len); + //If we have space, we need to see how much data we can request at most (if any available) + rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, j, (dci_tbs - ta_len - header_len - sdu_length_total)); // transport block set size + + //If data are available in channel j + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, + "[TEST]Have %d bytes in DCCH buffer during first call\n", + rlc_status.bytes_in_buffer); + //Fill in as much as possible + data_to_request = + cmin(dci_tbs - ta_len - header_len - + sdu_length_total, + rlc_status.bytes_in_buffer); + LOG_D(FLEXRAN_AGENT, + "Will request %d bytes from channel %d\n", + data_to_request, j); + if (data_to_request < 128) { //The header will be one byte less + header_len--; + header_len_last = 2; + } else { + header_len_last = 3; + } + /* if (j == 1 || j == 2) { + data_to_request+=0; + } */ + LOG_D(MAC, + "[TEST]Will request %d from channel %d\n", + data_to_request, j); + rlc_pdus[channels_added] = + (Protocol__FlexRlcPdu *) + malloc(sizeof(Protocol__FlexRlcPdu)); + protocol__flex_rlc_pdu__init(rlc_pdus + [channels_added]); + rlc_pdus[channels_added]->n_rlc_pdu_tb = 2; + rlc_pdus[channels_added]->rlc_pdu_tb = + (Protocol__FlexRlcPduTb **) + malloc(sizeof(Protocol__FlexRlcPduTb *) * + 2); + rlc_pdus[channels_added]->rlc_pdu_tb[0] = + (Protocol__FlexRlcPduTb *) + malloc(sizeof(Protocol__FlexRlcPduTb)); + protocol__flex_rlc_pdu_tb__init(rlc_pdus + [channels_added]->rlc_pdu_tb + [0]); + rlc_pdus[channels_added]-> + rlc_pdu_tb[0]->has_logical_channel_id = 1; + rlc_pdus[channels_added]-> + rlc_pdu_tb[0]->logical_channel_id = j; + rlc_pdus[channels_added]->rlc_pdu_tb[0]-> + has_size = 1; + rlc_pdus[channels_added]->rlc_pdu_tb[0]->size = + data_to_request; + rlc_pdus[channels_added]->rlc_pdu_tb[1] = + (Protocol__FlexRlcPduTb *) + malloc(sizeof(Protocol__FlexRlcPduTb)); + protocol__flex_rlc_pdu_tb__init(rlc_pdus + [channels_added]->rlc_pdu_tb + [1]); + rlc_pdus[channels_added]-> + rlc_pdu_tb[1]->has_logical_channel_id = 1; + rlc_pdus[channels_added]-> + rlc_pdu_tb[1]->logical_channel_id = j; + rlc_pdus[channels_added]->rlc_pdu_tb[1]-> + has_size = 1; + rlc_pdus[channels_added]->rlc_pdu_tb[1]->size = + data_to_request; + dl_data[num_ues_added]->n_rlc_pdu++; + channels_added++; + //Set this to the max value that we might request + sdu_length_total += data_to_request; + } else { + //Take back the assumption of a header for this channel + header_len -= 3; + } //End rlc_status.bytes_in_buffer <= 0 + } //end of if dci_tbs - ta_len - header_len > 0 + } // End of iterating the logical channels + + // Add rlc_pdus to the dl_data message + dl_data[num_ues_added]->rlc_pdu = (Protocol__FlexRlcPdu **) + malloc(sizeof(Protocol__FlexRlcPdu *) * + dl_data[num_ues_added]->n_rlc_pdu); + for (i = 0; i < dl_data[num_ues_added]->n_rlc_pdu; i++) { + dl_data[num_ues_added]->rlc_pdu[i] = rlc_pdus[i]; + } + + if (header_len == 0) { + LOG_D(FLEXRAN_AGENT, "Header was empty\n"); + header_len_last = 0; + } + // there is a payload + if ((dl_data[num_ues_added]->n_rlc_pdu > 0)) { + // Now compute number of required RBs for total sdu length + // Assume RAH format 2 + // adjust header lengths + LOG_D(FLEXRAN_AGENT, "We have %d bytes to transfer\n", + sdu_length_total); + if (header_len != 0) { + LOG_D(FLEXRAN_AGENT, "Header length was %d ", + header_len); + header_len_last--; + header_len -= header_len_last; + LOG_D(FLEXRAN_AGENT, "so we resized it to %d\n", + header_len); + } + + /* if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field */ + /* header_len = 1; */ + /* } else { //Remove length field from the last SDU */ + /* header_len--; */ + /* } */ + + mcs_tmp = mcs; + if (mcs_tmp == 0) { + nb_rb = 4; // don't let the TBS get too small + } else { + nb_rb = min_rb_unit[CC_id]; + } + + LOG_D(MAC, + "[TEST]The initial number of resource blocks was %d\n", + nb_rb); + LOG_D(MAC, "[TEST] The initial mcs was %d\n", mcs_tmp); + + TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); + LOG_D(MAC, + "[TEST]The TBS during rate matching was %d\n", + TBS); + + while (TBS < (sdu_length_total + header_len + ta_len)) { + nb_rb += min_rb_unit[CC_id]; // + LOG_D(MAC, + "[TEST]Had to increase the number of RBs\n"); + 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(mcs_tmp, + nb_available_rb); + nb_rb = nb_available_rb; + break; + } + + TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); + } + + if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { + LOG_D(MAC, + "[TEST]We had the exact number of rbs. Time to fill the rballoc subband\n"); + for (j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band + UE_list->UE_template[CC_id][UE_id]. + rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + LOG_D(MAC, + "[TEST]Will only partially fill the bitmap\n"); + while ((nb_rb_temp > 0) + && (j < flexran_get_N_RBG(mod_id, CC_id))) { + if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == + 1) { + UE_list-> + UE_template[CC_id] + [UE_id].rballoc_subband[harq_pid][j] = + ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + if ((j == + flexran_get_N_RBG(mod_id, CC_id) - 1) + && + ((flexran_get_N_RB_DL(mod_id, CC_id) == + 25) + || (flexran_get_N_RB_DL(mod_id, CC_id) + == 50))) { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id] + + 1; + } else { + nb_rb_temp = + nb_rb_temp - min_rb_unit[CC_id]; + } + } + j = j + 1; + } + } + + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].dl_pow_off = + ue_sched_ctl->dl_pow_off[CC_id]; + + for (j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { + PHY_vars_eNB_g[mod_id][CC_id]-> + mu_mimo_mode[UE_id].rballoc_sub[j] = + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband + [harq_pid][j]; + } + + // decrease mcs until TBS falls below required length + while ((TBS > (sdu_length_total + header_len + ta_len)) + && (mcs_tmp > 0)) { + mcs_tmp--; + TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); + } + + // if we have decreased too much or we don't have enough RBs, increase MCS + while ((TBS < (sdu_length_total + header_len + ta_len)) + && (((ue_sched_ctl->dl_pow_off[CC_id] > 0) + && (mcs_tmp < 28)) + || ((ue_sched_ctl->dl_pow_off[CC_id] == 0) + && (mcs_tmp <= 15)))) { + mcs_tmp++; + TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); + } + + dci_tbs = TBS; + mcs = mcs_tmp; + LOG_D(FLEXRAN_AGENT, "Final mcs was %d\n", mcs); + + dl_dci->has_aggr_level = 1; + dl_dci->aggr_level = aggregation; + + UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = + nb_rb; + + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + UE_list->UE_template[CC_id][UE_id].DAI++; + // printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); + //#warning only for 5MHz channel + update_ul_dci(mod_id, CC_id, rnti, + UE_list->UE_template[CC_id][UE_id]. + DAI); + } + // do PUCCH power control + // this is the normalized RX power + normalized_rx_power = flexran_get_p0_pucch_dbm(mod_id, UE_id, CC_id); //eNB_UE_stats->Po_PUCCH_dBm; + target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 20; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 20; + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = + UE_list->UE_template[CC_id][UE_id]. + pucch_tpc_tx_frame * 10 + + UE_list->UE_template[CC_id][UE_id]. + pucch_tpc_tx_subframe; + + if (((framex10psubframe + 10) <= (frame * 10 + subframe)) || //normal case + ((framex10psubframe > (frame * 10 + subframe)) && (((10240 - framex10psubframe + frame * 10 + subframe) >= 10)))) //frame wrap-around + if (flexran_get_p0_pucch_status + (mod_id, UE_id, CC_id) == 1) { + flexran_update_p0_pucch(mod_id, UE_id, CC_id); + + UE_list-> + UE_template[CC_id] + [UE_id].pucch_tpc_tx_frame = frame; + UE_list-> + UE_template[CC_id] + [UE_id].pucch_tpc_tx_subframe = subframe; + if (normalized_rx_power > + (target_rx_power + 1)) { + tpc = 0; //-1 + tpc_accumulated--; + } else if (normalized_rx_power < + (target_rx_power - 1)) { + tpc = 2; //+1 + tpc_accumulated++; + } else { + tpc = 1; //0 + } + LOG_D(MAC, + "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + mod_id, frame, subframe, harq_pid, tpc, + tpc_accumulated, normalized_rx_power, + target_rx_power); + } // Po_PUCCH has been updated + else { + tpc = 1; //0 + } // time to do TPC update + else { + tpc = 1; //0 + } + + for (i = 0; + i < + PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RBG; + i++) { + rballoc_sub[i] = + UE_list-> + UE_template[CC_id][UE_id].rballoc_subband + [harq_pid][i]; + } + + // Toggle NDI + LOG_D(MAC, + "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, frame, subframe, UE_id, + UE_list->UE_template[CC_id][UE_id].rnti, + harq_pid, + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]); + UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid] = + 1 - + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + ndi = + UE_list->UE_template[CC_id][UE_id]. + oldNDI[harq_pid]; + + UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs; + UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid] = + tpc; + + // Increase the pointer for the number of scheduled UEs + num_ues_added++; + ue_has_transmission = 1; + } else { // There is no data from RLC or MAC header, so don't schedule + ue_has_transmission = 0; + } + } // End of new scheduling + + // If we has transmission or retransmission + if (ue_has_transmission) { + switch (mac_xface-> + get_transmission_mode(mod_id, CC_id, rnti)) { + case 1: + case 2: + default: + dl_dci->has_res_alloc = 1; + dl_dci->res_alloc = 0; + dl_dci->has_vrb_format = 1; + dl_dci->vrb_format = + PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; + dl_dci->has_format = 1; + dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1; + dl_dci->has_rb_bitmap = 1; + dl_dci->rb_bitmap = + allocate_prbs_sub(nb_rb, rballoc_sub); + dl_dci->has_rb_shift = 1; + dl_dci->rb_shift = 0; + dl_dci->n_ndi = 1; + dl_dci->ndi = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_ndi); + dl_dci->ndi[0] = ndi; + dl_dci->n_rv = 1; + dl_dci->rv = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_rv); + dl_dci->rv[0] = round & 3; + dl_dci->has_tpc = 1; + dl_dci->tpc = tpc; + dl_dci->n_mcs = 1; + dl_dci->mcs = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_mcs); + dl_dci->mcs[0] = mcs; + dl_dci->n_tbs_size = 1; + dl_dci->tbs_size = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_tbs_size); + dl_dci->tbs_size[0] = dci_tbs; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + dl_dci->has_dai = 1; + dl_dci->dai = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + } + break; + case 3: + dl_dci->has_res_alloc = 1; + dl_dci->res_alloc = 0; + dl_dci->has_vrb_format = 1; + dl_dci->vrb_format = + PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; + dl_dci->has_format = 1; + dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A; + dl_dci->has_rb_bitmap = 1; + dl_dci->rb_bitmap = + allocate_prbs_sub(nb_rb, rballoc_sub); + dl_dci->has_rb_shift = 1; + dl_dci->rb_shift = 0; + dl_dci->n_ndi = 2; + dl_dci->ndi = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_ndi); + dl_dci->ndi[0] = ndi; + dl_dci->ndi[1] = ndi; + dl_dci->n_rv = 2; + dl_dci->rv = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_rv); + dl_dci->rv[0] = round & 3; + dl_dci->rv[1] = round & 3; + dl_dci->has_tpc = 1; + dl_dci->tpc = tpc; + dl_dci->n_mcs = 2; + dl_dci->mcs = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_mcs); + dl_dci->mcs[0] = mcs; + dl_dci->mcs[1] = mcs; + dl_dci->n_tbs_size = 2; + dl_dci->tbs_size = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_tbs_size); + dl_dci->tbs_size[0] = dci_tbs; + dl_dci->tbs_size[1] = dci_tbs; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + dl_dci->has_dai = 1; + dl_dci->dai = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + } + break; + case 4: + dl_dci->has_res_alloc = 1; + dl_dci->res_alloc = 0; + dl_dci->has_vrb_format = 1; + dl_dci->vrb_format = + PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; + dl_dci->has_format = 1; + dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A; + dl_dci->has_rb_bitmap = 1; + dl_dci->rb_bitmap = + allocate_prbs_sub(nb_rb, rballoc_sub); + dl_dci->has_rb_shift = 1; + dl_dci->rb_shift = 0; + dl_dci->n_ndi = 2; + dl_dci->ndi = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_ndi); + dl_dci->ndi[0] = ndi; + dl_dci->ndi[1] = ndi; + dl_dci->n_rv = 2; + dl_dci->rv = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_rv); + dl_dci->rv[0] = round & 3; + dl_dci->rv[1] = round & 3; + dl_dci->has_tpc = 1; + dl_dci->tpc = tpc; + dl_dci->n_mcs = 2; + dl_dci->mcs = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_mcs); + dl_dci->mcs[0] = mcs; + dl_dci->mcs[1] = mcs; + dl_dci->n_tbs_size = 2; + dl_dci->tbs_size = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_tbs_size); + dl_dci->tbs_size[0] = dci_tbs; + dl_dci->tbs_size[1] = dci_tbs; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + dl_dci->has_dai = 1; + dl_dci->dai = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + } + break; + case 5: + dl_dci->has_res_alloc = 1; + dl_dci->res_alloc = 0; + dl_dci->has_vrb_format = 1; + dl_dci->vrb_format = + PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; + dl_dci->has_format = 1; + dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D; + dl_dci->has_rb_bitmap = 1; + dl_dci->rb_bitmap = + allocate_prbs_sub(nb_rb, rballoc_sub); + dl_dci->has_rb_shift = 1; + dl_dci->rb_shift = 0; + dl_dci->n_ndi = 1; + dl_dci->ndi[0] = ndi; + dl_dci->n_rv = 1; + dl_dci->rv = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_rv); + dl_dci->rv[0] = round & 3; + dl_dci->has_tpc = 1; + dl_dci->tpc = tpc; + dl_dci->n_mcs = 1; + dl_dci->mcs = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_mcs); + dl_dci->mcs[0] = mcs; + dl_dci->n_tbs_size = 1; + dl_dci->tbs_size = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_tbs_size); + dl_dci->tbs_size[0] = dci_tbs; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + dl_dci->has_dai = 1; + dl_dci->dai = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + } + + if (ue_sched_ctl->dl_pow_off[CC_id] == 2) { + ue_sched_ctl->dl_pow_off[CC_id] = 1; + } + + dl_dci->has_dl_power_offset = 1; + dl_dci->dl_power_offset = + ue_sched_ctl->dl_pow_off[CC_id]; + dl_dci->has_precoding_info = 1; + dl_dci->precoding_info = 5; // Is this right?? + + break; + case 6: + dl_dci->has_res_alloc = 1; + dl_dci->res_alloc = 0; + dl_dci->has_vrb_format = 1; + dl_dci->vrb_format = + PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; + dl_dci->has_format = 1; + dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D; + dl_dci->has_rb_bitmap = 1; + dl_dci->rb_bitmap = + allocate_prbs_sub(nb_rb, rballoc_sub); + dl_dci->has_rb_shift = 1; + dl_dci->rb_shift = 0; + dl_dci->n_ndi = 1; + dl_dci->ndi = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_ndi); + dl_dci->ndi[0] = ndi; + dl_dci->n_rv = 1; + dl_dci->rv = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_rv); + dl_dci->rv[0] = round & 3; + dl_dci->has_tpc = 1; + dl_dci->tpc = tpc; + dl_dci->n_mcs = 1; + dl_dci->mcs = + (uint32_t *) malloc(sizeof(uint32_t) * + dl_dci->n_mcs); + dl_dci->mcs[0] = mcs; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + dl_dci->has_dai = 1; + dl_dci->dai = + (UE_list->UE_template[CC_id][UE_id].DAI - + 1) & 3; + } + + dl_dci->has_dl_power_offset = 1; + dl_dci->dl_power_offset = + ue_sched_ctl->dl_pow_off[CC_id]; + dl_dci->has_precoding_info = 1; + dl_dci->precoding_info = 5; // Is this right?? + break; } - } - j = j + 1; } - } - - nb_available_rb -= nb_rb; - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; - - for(j=0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; - rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; - } - - // Keep the old NDI, do not toggle - ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - tpc = UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid]; - UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs; - - ue_has_transmission = 1; - num_ues_added++; - } else { - LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", - mod_id, frame, CC_id, UE_id); - ue_has_transmission = 0; - } - //End of retransmission - } else { /* This is a potentially new SDU opportunity */ - 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(mcs, nb_available_rb); - dci_tbs = TBS; - LOG_D(FLEXRAN_AGENT, "TBS is %d\n", TBS); - - // check first for RLC data on DCCH - // add the length for all the control elements (timing adv, drx, etc) : header + payload - - ta_len = (ue_sched_ctl->ta_update != 0) ? 2 : 0; - - dl_data[num_ues_added]->n_ce_bitmap = 2; - dl_data[num_ues_added]->ce_bitmap = (uint32_t *) calloc(2, sizeof(uint32_t)); - - if (ta_len > 0) { - ce_flags |= PROTOCOL__FLEX_CE_TYPE__FLPCET_TA; - } - /*TODO: Add other flags if DRX and other CE are required*/ - - // Add the control element flags to the flexran message - dl_data[num_ues_added]->ce_bitmap[0] = ce_flags; - dl_data[num_ues_added]->ce_bitmap[1] = ce_flags; - - // TODO : Need to prioritize DRBs - // Loop through the UE logical channels (DCCH, DCCH1, DTCH for now) - header_len = 0; - header_len_last = 0; - sdu_length_total = 0; - for (j = 1; j < NB_RB_MAX; j++) { - header_len += 3; - // Need to see if we have space for data from this channel - if (dci_tbs - ta_len - header_len - sdu_length_total > 0) { - LOG_D(MAC, "[TEST]Requested %d bytes from RLC buffer on channel %d during first call\n", dci_tbs-ta_len-header_len); - //If we have space, we need to see how much data we can request at most (if any available) - rlc_status = mac_rlc_status_ind(mod_id, - rnti, - mod_id, - frame, - subframe, - ENB_FLAG_YES, - MBMS_FLAG_NO, - j, - (dci_tbs - ta_len - header_len - sdu_length_total)); // transport block set size - - //If data are available in channel j - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[TEST]Have %d bytes in DCCH buffer during first call\n", rlc_status.bytes_in_buffer); - //Fill in as much as possible - data_to_request = cmin(dci_tbs - ta_len - header_len - sdu_length_total, rlc_status.bytes_in_buffer); - LOG_D(FLEXRAN_AGENT, "Will request %d bytes from channel %d\n", data_to_request, j); - if (data_to_request < 128) { //The header will be one byte less - header_len--; - header_len_last = 2; - } else { - header_len_last = 3; - } - /* if (j == 1 || j == 2) { - data_to_request+=0; - } */ - LOG_D(MAC, "[TEST]Will request %d from channel %d\n", data_to_request, j); - rlc_pdus[channels_added] = (Protocol__FlexRlcPdu *) malloc(sizeof(Protocol__FlexRlcPdu)); - protocol__flex_rlc_pdu__init(rlc_pdus[channels_added]); - rlc_pdus[channels_added]->n_rlc_pdu_tb = 2; - rlc_pdus[channels_added]->rlc_pdu_tb = (Protocol__FlexRlcPduTb **) malloc(sizeof(Protocol__FlexRlcPduTb *) * 2); - rlc_pdus[channels_added]->rlc_pdu_tb[0] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb)); - protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[0]); - rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_logical_channel_id = 1; - rlc_pdus[channels_added]->rlc_pdu_tb[0]->logical_channel_id = j; - rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_size = 1; - rlc_pdus[channels_added]->rlc_pdu_tb[0]->size = data_to_request; - rlc_pdus[channels_added]->rlc_pdu_tb[1] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb)); - protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[1]); - rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_logical_channel_id = 1; - rlc_pdus[channels_added]->rlc_pdu_tb[1]->logical_channel_id = j; - rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_size = 1; - rlc_pdus[channels_added]->rlc_pdu_tb[1]->size = data_to_request; - dl_data[num_ues_added]->n_rlc_pdu++; - channels_added++; - //Set this to the max value that we might request - sdu_length_total += data_to_request; - } else { - //Take back the assumption of a header for this channel - header_len -= 3; - } //End rlc_status.bytes_in_buffer <= 0 - } //end of if dci_tbs - ta_len - header_len > 0 - } // End of iterating the logical channels - - // Add rlc_pdus to the dl_data message - dl_data[num_ues_added]->rlc_pdu = (Protocol__FlexRlcPdu **) malloc(sizeof(Protocol__FlexRlcPdu *) * - dl_data[num_ues_added]->n_rlc_pdu); - for (i = 0; i < dl_data[num_ues_added]->n_rlc_pdu; i++) { - dl_data[num_ues_added]->rlc_pdu[i] = rlc_pdus[i]; + if (flexran_get_duplex_mode(mod_id, CC_id) == + PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { + + /* TODO */ + //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe, frame_parms); + } + } // UE_id loop + } // CC_id loop + + // Add all the dl_data elements to the flexran message + int offset = (*dl_info)->dl_mac_config_msg->n_dl_ue_data; + (*dl_info)->dl_mac_config_msg->n_dl_ue_data += num_ues_added; + if (num_ues_added > 0) { + (*dl_info)->dl_mac_config_msg->dl_ue_data = + (Protocol__FlexDlData **) + realloc((*dl_info)->dl_mac_config_msg->dl_ue_data, + sizeof(Protocol__FlexDlData *) * + ((*dl_info)->dl_mac_config_msg->n_dl_ue_data)); + if ((*dl_info)->dl_mac_config_msg->dl_ue_data == NULL) { + LOG_E(MAC, "Request for memory reallocation failed\n"); + return; } - - if (header_len == 0) { - LOG_D(FLEXRAN_AGENT, "Header was empty\n"); - header_len_last = 0; - } - - // there is a payload - if ((dl_data[num_ues_added]->n_rlc_pdu > 0)) { - // Now compute number of required RBs for total sdu length - // Assume RAH format 2 - // adjust header lengths - LOG_D(FLEXRAN_AGENT, "We have %d bytes to transfer\n", sdu_length_total); - if (header_len != 0) { - LOG_D(FLEXRAN_AGENT, "Header length was %d ", header_len); - header_len_last--; - header_len -= header_len_last; - LOG_D(FLEXRAN_AGENT, "so we resized it to %d\n", header_len); - } - - /* if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field */ - /* header_len = 1; */ - /* } else { //Remove length field from the last SDU */ - /* header_len--; */ - /* } */ - - mcs_tmp = mcs; - if (mcs_tmp == 0) { - nb_rb = 4; // don't let the TBS get too small - } else { - nb_rb=min_rb_unit[CC_id]; - } - - LOG_D(MAC,"[TEST]The initial number of resource blocks was %d\n", nb_rb); - LOG_D(MAC,"[TEST] The initial mcs was %d\n", mcs_tmp); - - TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); - LOG_D(MAC,"[TEST]The TBS during rate matching was %d\n", TBS); - - while (TBS < (sdu_length_total + header_len + ta_len)) { - nb_rb += min_rb_unit[CC_id]; // - LOG_D(MAC, "[TEST]Had to increase the number of RBs\n"); - 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(mcs_tmp, nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); - } - - if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { - LOG_D(MAC, "[TEST]We had the exact number of rbs. Time to fill the rballoc subband\n"); - for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - LOG_D(MAC, "[TEST]Will only partially fill the bitmap\n"); - while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) { - if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; - if ((j == flexran_get_N_RBG(mod_id, CC_id) - 1) && - ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)|| - (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; - } - } - j = j+1; - } - } - - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; - - for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { - PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; - } - - // decrease mcs until TBS falls below required length - while ((TBS > (sdu_length_total + header_len + ta_len)) && (mcs_tmp > 0)) { - mcs_tmp--; - TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); - } - - // if we have decreased too much or we don't have enough RBs, increase MCS - while ((TBS < (sdu_length_total + header_len + ta_len)) && - ((( ue_sched_ctl->dl_pow_off[CC_id] > 0) && (mcs_tmp < 28)) || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs_tmp <= 15)))) { - mcs_tmp++; - TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb); - } - - dci_tbs = TBS; - mcs = mcs_tmp; - LOG_D(FLEXRAN_AGENT, "Final mcs was %d\n", mcs); - - dl_dci->has_aggr_level = 1; - dl_dci->aggr_level = aggregation; - - UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; - - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - UE_list->UE_template[CC_id][UE_id].DAI++; - // printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); - //#warning only for 5MHz channel - update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI); - } - - // do PUCCH power control - // this is the normalized RX power - normalized_rx_power = flexran_get_p0_pucch_dbm(mod_id,UE_id, CC_id); //eNB_UE_stats->Po_PUCCH_dBm; - target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 20; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 20; - // this assumes accumulated tpc - // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; - - if (((framex10psubframe+10)<=(frame*10+subframe)) || //normal case - ((framex10psubframe>(frame*10+subframe)) && (((10240-framex10psubframe+frame*10+subframe)>=10)))) //frame wrap-around - if (flexran_get_p0_pucch_status(mod_id, UE_id, CC_id) == 1) { - flexran_update_p0_pucch(mod_id, UE_id, CC_id); - - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frame; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframe; - if (normalized_rx_power>(target_rx_power+1)) { - tpc = 0; //-1 - tpc_accumulated--; - } else if (normalized_rx_power<(target_rx_power-1)) { - tpc = 2; //+1 - tpc_accumulated++; - } else { - tpc = 1; //0 - } - LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", - mod_id, frame, subframe, harq_pid, tpc, - tpc_accumulated, normalized_rx_power, target_rx_power); - } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 - } - - for(i=0; i<PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RBG; i++) { - rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; - } - - // Toggle NDI - LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, frame, subframe, UE_id, - UE_list->UE_template[CC_id][UE_id].rnti,harq_pid, UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]= 1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - - UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid] = tpc; - - // Increase the pointer for the number of scheduled UEs - num_ues_added++; - ue_has_transmission = 1; - } else { // There is no data from RLC or MAC header, so don't schedule - ue_has_transmission = 0; + for (i = 0; i < num_ues_added; i++) { + (*dl_info)->dl_mac_config_msg->dl_ue_data[offset + i] = + dl_data[i]; } - } // End of new scheduling - - // If we has transmission or retransmission - if (ue_has_transmission) { - switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) { - case 1: - case 2: - default: - dl_dci->has_res_alloc = 1; - dl_dci->res_alloc = 0; - dl_dci->has_vrb_format = 1; - dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; - dl_dci->has_format = 1; - dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1; - dl_dci->has_rb_bitmap = 1; - dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub); - dl_dci->has_rb_shift = 1; - dl_dci->rb_shift = 0; - dl_dci->n_ndi = 1; - dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi); - dl_dci->ndi[0] = ndi; - dl_dci->n_rv = 1; - dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv); - dl_dci->rv[0] = round & 3; - dl_dci->has_tpc = 1; - dl_dci->tpc = tpc; - dl_dci->n_mcs = 1; - dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs); - dl_dci->mcs[0] = mcs; - dl_dci->n_tbs_size = 1; - dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size); - dl_dci->tbs_size[0] = dci_tbs; - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - dl_dci->has_dai = 1; - dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - } - break; - case 3: - dl_dci->has_res_alloc = 1; - dl_dci->res_alloc = 0; - dl_dci->has_vrb_format = 1; - dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; - dl_dci->has_format = 1; - dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A; - dl_dci->has_rb_bitmap = 1; - dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub); - dl_dci->has_rb_shift = 1; - dl_dci->rb_shift = 0; - dl_dci->n_ndi = 2; - dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi); - dl_dci->ndi[0] = ndi; - dl_dci->ndi[1] = ndi; - dl_dci->n_rv = 2; - dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv); - dl_dci->rv[0] = round & 3; - dl_dci->rv[1] = round & 3; - dl_dci->has_tpc = 1; - dl_dci->tpc = tpc; - dl_dci->n_mcs = 2; - dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs); - dl_dci->mcs[0] = mcs; - dl_dci->mcs[1] = mcs; - dl_dci->n_tbs_size = 2; - dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size); - dl_dci->tbs_size[0] = dci_tbs; - dl_dci->tbs_size[1] = dci_tbs; - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - dl_dci->has_dai = 1; - dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - } - break; - case 4: - dl_dci->has_res_alloc = 1; - dl_dci->res_alloc = 0; - dl_dci->has_vrb_format = 1; - dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; - dl_dci->has_format = 1; - dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A; - dl_dci->has_rb_bitmap = 1; - dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub); - dl_dci->has_rb_shift = 1; - dl_dci->rb_shift = 0; - dl_dci->n_ndi = 2; - dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi); - dl_dci->ndi[0] = ndi; - dl_dci->ndi[1] = ndi; - dl_dci->n_rv = 2; - dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv); - dl_dci->rv[0] = round & 3; - dl_dci->rv[1] = round & 3; - dl_dci->has_tpc = 1; - dl_dci->tpc = tpc; - dl_dci->n_mcs = 2; - dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs); - dl_dci->mcs[0] = mcs; - dl_dci->mcs[1] = mcs; - dl_dci->n_tbs_size = 2; - dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size); - dl_dci->tbs_size[0] = dci_tbs; - dl_dci->tbs_size[1] = dci_tbs; - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - dl_dci->has_dai = 1; - dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - } - break; - case 5: - dl_dci->has_res_alloc = 1; - dl_dci->res_alloc = 0; - dl_dci->has_vrb_format = 1; - dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; - dl_dci->has_format = 1; - dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D; - dl_dci->has_rb_bitmap = 1; - dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub); - dl_dci->has_rb_shift = 1; - dl_dci->rb_shift = 0; - dl_dci->n_ndi = 1; - dl_dci->ndi[0] = ndi; - dl_dci->n_rv = 1; - dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv); - dl_dci->rv[0] = round & 3; - dl_dci->has_tpc = 1; - dl_dci->tpc = tpc; - dl_dci->n_mcs = 1; - dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs); - dl_dci->mcs[0] = mcs; - dl_dci->n_tbs_size = 1; - dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size); - dl_dci->tbs_size[0] = dci_tbs; - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - dl_dci->has_dai = 1; - dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - } - - if(ue_sched_ctl->dl_pow_off[CC_id] == 2) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - dl_dci->has_dl_power_offset = 1; - dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id]; - dl_dci->has_precoding_info = 1; - dl_dci->precoding_info = 5; // Is this right?? - - break; - case 6: - dl_dci->has_res_alloc = 1; - dl_dci->res_alloc = 0; - dl_dci->has_vrb_format = 1; - dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED; - dl_dci->has_format = 1; - dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D; - dl_dci->has_rb_bitmap = 1; - dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub); - dl_dci->has_rb_shift = 1; - dl_dci->rb_shift = 0; - dl_dci->n_ndi = 1; - dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi); - dl_dci->ndi[0] = ndi; - dl_dci->n_rv = 1; - dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv); - dl_dci->rv[0] = round & 3; - dl_dci->has_tpc = 1; - dl_dci->tpc = tpc; - dl_dci->n_mcs = 1; - dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs); - dl_dci->mcs[0] = mcs; - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - dl_dci->has_dai = 1; - dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; - } - - dl_dci->has_dl_power_offset = 1; - dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id]; - dl_dci->has_precoding_info = 1; - dl_dci->precoding_info = 5; // Is this right?? - break; - } - } - - if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) { - - /* TODO */ - //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe, frame_parms); - } - } // UE_id loop - } // CC_id loop - - // Add all the dl_data elements to the flexran message - int offset = (*dl_info)->dl_mac_config_msg->n_dl_ue_data; - (*dl_info)->dl_mac_config_msg->n_dl_ue_data += num_ues_added; - if ( num_ues_added > 0 ){ - (*dl_info)->dl_mac_config_msg->dl_ue_data = (Protocol__FlexDlData **) realloc( (*dl_info)->dl_mac_config_msg->dl_ue_data, - sizeof(Protocol__FlexDlData *) * ((*dl_info)->dl_mac_config_msg->n_dl_ue_data)); - if ((*dl_info)->dl_mac_config_msg->dl_ue_data == NULL ){ - LOG_E(MAC, "Request for memory reallocation failed\n"); - return; - } - for (i = 0; i < num_ues_added; i++) { - (*dl_info)->dl_mac_config_msg->dl_ue_data[offset+i] = dl_data[i]; - } - } - - stop_meas(&eNB->schedule_dlsch); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT); + } + + stop_meas(&eNB->schedule_dlsch); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c index 17424b27970c806dd1bb8413e4ed852530d9b878..68c86f1da54671e4110c5bb6bb8a610be210725a 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_agent_scheduler_dlsch_ue_remote.c * \brief procedures related to remote scheduling in the DLSCH transport channel @@ -44,137 +44,159 @@ int queue_initialized = 0; //uint32_t period = 10; //uint32_t sched [] = {1, 2, 3}; -void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe, - int *mbsfn_flag, Protocol__FlexranMessage **dl_info) { - - - //if ((subframe == skip_subframe) && (frame % period == 0)) { - // LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame); - // for (int i = 0; i < 3; i++) { - // LOG_I(MAC, "%d\n", sched[i]); - // } - //} - - /* if (frame == 500 && subframe == 1) { */ - /* char policy[] = "rrc: \n - ul_scheduler: \n behavior : tester_function\n parameters:\n period: !!int 3\nmac: \n - dl_scheduler: \n parameters: \n period : !!int 40\n skip_subframe : !!int 3\n sched : [!!int 4, !!int 5, !!int 6]"; */ - /* apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */ - /* } */ - - eNB_MAC_INST *eNB; - - if (!queue_initialized) { - TAILQ_INIT(&queue_head); - queue_initialized = 1; - } - - eNB = &eNB_mac_inst[mod_id]; - - dl_mac_config_element_t *dl_config_elem; - - int diff; - LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, subframe); - // First we check to see if we have a scheduling decision for this sfn_sf already in our queue - while(queue_head.tqh_first != NULL) { - dl_config_elem = queue_head.tqh_first; - - diff = get_sf_difference(mod_id, dl_config_elem->dl_info->dl_mac_config_msg->sfn_sf); - // Check if this decision is for now, for a later or a previous subframe - if ( diff == 0) { // Now - LOG_D(MAC, "Found a decision for this subframe in the queue. Let's use it!\n"); - TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs); - *dl_info = dl_config_elem->dl_info; - free(dl_config_elem); - eNB->eNB_stats[mod_id].sched_decisions++; - return; - } else if (diff < 0) { //previous subframe , delete message and free memory - LOG_D(MAC, "Found a decision for a previous subframe in the queue. Let's get rid of it\n"); - TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs); - flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info); - free(dl_config_elem); - eNB->eNB_stats[mod_id].sched_decisions++; - eNB->eNB_stats[mod_id].missed_deadlines++; - } else { // next subframe, nothing to do now - LOG_D(MAC, "Found a decision for a future subframe in the queue. Nothing to do now\n"); - flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); - return; +void +flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, + uint32_t subframe, int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info) +{ + + + //if ((subframe == skip_subframe) && (frame % period == 0)) { + // LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame); + // for (int i = 0; i < 3; i++) { + // LOG_I(MAC, "%d\n", sched[i]); + // } + //} + + /* if (frame == 500 && subframe == 1) { */ + /* char policy[] = "rrc: \n - ul_scheduler: \n behavior : tester_function\n parameters:\n period: !!int 3\nmac: \n - dl_scheduler: \n parameters: \n period : !!int 40\n skip_subframe : !!int 3\n sched : [!!int 4, !!int 5, !!int 6]"; */ + /* apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */ + /* } */ + + eNB_MAC_INST *eNB; + + if (!queue_initialized) { + TAILQ_INIT(&queue_head); + queue_initialized = 1; } - } - - //Done with the local cache. Now we need to check if something new arrived - flexran_agent_get_pending_dl_mac_config(mod_id, dl_info); - while (*dl_info != NULL) { - - diff = get_sf_difference(mod_id, (*dl_info)->dl_mac_config_msg->sfn_sf); - if (diff == 0) { // Got a command for this sfn_sf - LOG_D(MAC, "Found a decision for this subframe pending. Let's use it\n"); - eNB->eNB_stats[mod_id].sched_decisions++; - return; - } else if (diff < 0) { - LOG_D(MAC, "Found a decision for a previous subframe. Let's get rid of it\n"); - flexran_agent_mac_destroy_dl_config(*dl_info); - *dl_info = NULL; - flexran_agent_get_pending_dl_mac_config(mod_id, dl_info); - eNB->eNB_stats[mod_id].sched_decisions++; - eNB->eNB_stats[mod_id].missed_deadlines++; - } else { // Intended for future subframe. Store it in local cache - LOG_D(MAC, "Found a decision for a future subframe in the queue. Let's store it in the cache\n"); - dl_mac_config_element_t *e = malloc(sizeof(dl_mac_config_element_t)); - e->dl_info = *dl_info; - TAILQ_INSERT_TAIL(&queue_head, e, configs); - flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); - // No need to look for another. Messages arrive ordered - return; + + eNB = &eNB_mac_inst[mod_id]; + + dl_mac_config_element_t *dl_config_elem; + + int diff; + LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, + subframe); + // First we check to see if we have a scheduling decision for this sfn_sf already in our queue + while (queue_head.tqh_first != NULL) { + dl_config_elem = queue_head.tqh_first; + + diff = + get_sf_difference(mod_id, + dl_config_elem->dl_info-> + dl_mac_config_msg->sfn_sf); + // Check if this decision is for now, for a later or a previous subframe + if (diff == 0) { // Now + LOG_D(MAC, + "Found a decision for this subframe in the queue. Let's use it!\n"); + TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs); + *dl_info = dl_config_elem->dl_info; + free(dl_config_elem); + eNB->eNB_stats[mod_id].sched_decisions++; + return; + } else if (diff < 0) { //previous subframe , delete message and free memory + LOG_D(MAC, + "Found a decision for a previous subframe in the queue. Let's get rid of it\n"); + TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs); + flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info); + free(dl_config_elem); + eNB->eNB_stats[mod_id].sched_decisions++; + eNB->eNB_stats[mod_id].missed_deadlines++; + } else { // next subframe, nothing to do now + LOG_D(MAC, + "Found a decision for a future subframe in the queue. Nothing to do now\n"); + flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); + return; + } } - } - - // We found no pending command, so we will simply pass an empty one - flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); + + //Done with the local cache. Now we need to check if something new arrived + flexran_agent_get_pending_dl_mac_config(mod_id, dl_info); + while (*dl_info != NULL) { + + diff = + get_sf_difference(mod_id, + (*dl_info)->dl_mac_config_msg->sfn_sf); + if (diff == 0) { // Got a command for this sfn_sf + LOG_D(MAC, + "Found a decision for this subframe pending. Let's use it\n"); + eNB->eNB_stats[mod_id].sched_decisions++; + return; + } else if (diff < 0) { + LOG_D(MAC, + "Found a decision for a previous subframe. Let's get rid of it\n"); + flexran_agent_mac_destroy_dl_config(*dl_info); + *dl_info = NULL; + flexran_agent_get_pending_dl_mac_config(mod_id, dl_info); + eNB->eNB_stats[mod_id].sched_decisions++; + eNB->eNB_stats[mod_id].missed_deadlines++; + } else { // Intended for future subframe. Store it in local cache + LOG_D(MAC, + "Found a decision for a future subframe in the queue. Let's store it in the cache\n"); + dl_mac_config_element_t *e = + malloc(sizeof(dl_mac_config_element_t)); + e->dl_info = *dl_info; + TAILQ_INSERT_TAIL(&queue_head, e, configs); + flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); + // No need to look for another. Messages arrive ordered + return; + } + } + + // We found no pending command, so we will simply pass an empty one + flexran_agent_mac_create_empty_dl_config(mod_id, dl_info); } -int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) { - int diff_in_subframes; - - uint16_t current_frame = flexran_get_current_system_frame_num(mod_id); - uint16_t current_subframe = flexran_get_current_subframe(mod_id); - uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id); - - if (sfn_sf == current_sfn_sf) { - return 0; - } - - uint16_t frame_mask = ((1<<12) - 1); - uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4; - - uint16_t sf_mask = ((1<<4) - 1); - uint16_t subframe = (sfn_sf & sf_mask); - - LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, subframe); - - if (frame == current_frame) { - return subframe - current_subframe; - } else if (frame > current_frame) { - diff_in_subframes = ((frame*10)+subframe) - ((current_frame*10)+current_subframe); - - // diff_in_subframes = 9 - current_subframe; - //diff_in_subframes += (subframe + 1); - //diff_in_subframes += (frame-2) * 10; - if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) { - return -1; - } else { - return 1; +int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) +{ + int diff_in_subframes; + + uint16_t current_frame = flexran_get_current_system_frame_num(mod_id); + uint16_t current_subframe = flexran_get_current_subframe(mod_id); + uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id); + + if (sfn_sf == current_sfn_sf) { + return 0; } - } else { //frame < current_frame - //diff_in_subframes = 9 - current_subframe; - //diff_in_subframes += (subframe + 1); - //if (frame > 0) { - // diff_in_subframes += (frame - 1) * 10; - //} - //diff_in_subframes += (1023 - current_frame) * 10; - diff_in_subframes = 10240 - ((current_frame*10)+current_subframe) + ((frame*10)+subframe); - if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) { - return -1; - } else { - return 1; + + uint16_t frame_mask = ((1 << 12) - 1); + uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4; + + uint16_t sf_mask = ((1 << 4) - 1); + uint16_t subframe = (sfn_sf & sf_mask); + + LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, + subframe); + + if (frame == current_frame) { + return subframe - current_subframe; + } else if (frame > current_frame) { + diff_in_subframes = + ((frame * 10) + subframe) - ((current_frame * 10) + + current_subframe); + + // diff_in_subframes = 9 - current_subframe; + //diff_in_subframes += (subframe + 1); + //diff_in_subframes += (frame-2) * 10; + if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) { + return -1; + } else { + return 1; + } + } else { //frame < current_frame + //diff_in_subframes = 9 - current_subframe; + //diff_in_subframes += (subframe + 1); + //if (frame > 0) { + // diff_in_subframes += (frame - 1) * 10; + //} + //diff_in_subframes += (1023 - current_frame) * 10; + diff_in_subframes = + 10240 - ((current_frame * 10) + current_subframe) + + ((frame * 10) + subframe); + if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) { + return -1; + } else { + return 1; + } } - } } diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h index 997b9d1d24d5dc4b9cc454decf2cb7563b781e8b..449ba1e8cde85e8c6001178f9e68534590b9952f 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_agent_scheduler_dlsch_ue_remote.h * \brief Local stub for remote scheduler used by the controller @@ -46,8 +46,8 @@ #define SCHED_AHEAD_SUBFRAMES 20 typedef struct dl_mac_config_element_s { - Protocol__FlexranMessage *dl_info; - TAILQ_ENTRY(dl_mac_config_element_s) configs; + Protocol__FlexranMessage *dl_info; + TAILQ_ENTRY(dl_mac_config_element_s) configs; } dl_mac_config_element_t; TAILQ_HEAD(DlMacConfigHead, dl_mac_config_element_s); @@ -55,8 +55,9 @@ TAILQ_HEAD(DlMacConfigHead, dl_mac_config_element_s); /* * Default scheduler used by the eNB agent */ -void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe, - int *mbsfn_flag, Protocol__FlexranMessage **dl_info); +void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, + uint32_t subframe, int *mbsfn_flag, + Protocol__FlexranMessage ** dl_info); // Find the difference in subframes from the given subframe diff --git a/openair2/LAYER2/MAC/flexran_dci_conversions.h b/openair2/LAYER2/MAC/flexran_dci_conversions.h index f52ae5b807207426cdc6e79298bd1d11515436cd..5c18b431043f47033b739f314c1ea98ea3ab20cb 100644 --- a/openair2/LAYER2/MAC/flexran_dci_conversions.h +++ b/openair2/LAYER2/MAC/flexran_dci_conversions.h @@ -17,7 +17,7 @@ *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org - */ + */ /*! \file flexran_dci_conversions.h * \brief Conversion helpers from flexran messages to OAI formats DCI @@ -47,5 +47,5 @@ ((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \ ((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \ ((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0]; - + #endif diff --git a/openair2/LAYER2/MAC/l1_helpers.c b/openair2/LAYER2/MAC/l1_helpers.c index 2b5a38eda7cfc802e84da5391ab0724591676010..6e71f66ec5f56d32a52863db3fde89d6594b9b20 100644 --- a/openair2/LAYER2/MAC/l1_helpers.c +++ b/openair2/LAYER2/MAC/l1_helpers.c @@ -34,28 +34,36 @@ #include "UTIL/LOG/log.h" #include "proto.h" -int8_t get_Po_NOMINAL_PUSCH(module_id_t module_idP,uint8_t CC_id) +int8_t get_Po_NOMINAL_PUSCH(module_id_t module_idP, uint8_t CC_id) { - RACH_ConfigCommon_t *rach_ConfigCommon = NULL; + RACH_ConfigCommon_t *rach_ConfigCommon = NULL; - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon!=NULL, - "[UE %d] CCid %d FATAL radioResourceConfigCommon is NULL !!!\n",module_idP,CC_id); + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon != NULL, + "[UE %d] CCid %d FATAL radioResourceConfigCommon is NULL !!!\n", + module_idP, CC_id); - rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon; + rach_ConfigCommon = + &UE_mac_inst[module_idP].radioResourceConfigCommon-> + rach_ConfigCommon; - return(-120 + (rach_ConfigCommon->powerRampingParameters.preambleInitialReceivedTargetPower<<1) + - get_DELTA_PREAMBLE(module_idP,CC_id)); + return (-120 + + (rach_ConfigCommon-> + powerRampingParameters.preambleInitialReceivedTargetPower << + 1) + get_DELTA_PREAMBLE(module_idP, CC_id)); } -int8_t get_deltaP_rampup(module_id_t module_idP,uint8_t CC_id) +int8_t get_deltaP_rampup(module_id_t module_idP, uint8_t CC_id) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); - LOG_D(MAC,"[PUSCH]%d dB\n",UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER<<1); - return((int8_t)(UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER<<1)); + LOG_D(MAC, "[PUSCH]%d dB\n", + UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER << 1); + return ((int8_t) + (UE_mac_inst[module_idP]. + RA_PREAMBLE_TRANSMISSION_COUNTER << 1)); } diff --git a/openair2/LAYER2/MAC/lte_transport_init.c b/openair2/LAYER2/MAC/lte_transport_init.c index 1f67d8913c9c7392a959cb2a6282c8307b646aaa..e1f21f21e44935e7bf071b9377e6e69548201506 100644 --- a/openair2/LAYER2/MAC/lte_transport_init.c +++ b/openair2/LAYER2/MAC/lte_transport_init.c @@ -29,104 +29,104 @@ void init_transport_channels(unsigned char transmission_mode) { - // init DCI structures for testing - - UL_alloc_pdu.type = 0; - UL_alloc_pdu.hopping = 0; - UL_alloc_pdu.rballoc = UL_RB_ALLOC; - UL_alloc_pdu.mcs = 2; - UL_alloc_pdu.ndi = 1; - UL_alloc_pdu.TPC = 0; - UL_alloc_pdu.cqi_req = 1; - - /* - BCCH_alloc_pdu.type = 1; - BCCH_alloc_pdu.vrb_type = 0; - BCCH_alloc_pdu.rballoc = BCCH_RB_ALLOC; - BCCH_alloc_pdu.ndi = 1; - BCCH_alloc_pdu.rv = 1; - BCCH_alloc_pdu.mcs = 1; - BCCH_alloc_pdu.harq_pid = 0; - BCCH_alloc_pdu.TPC = 1; // set to 3 PRB - - // for FDD mode - BCCH_alloc_pdu_fdd.type = 1; - BCCH_alloc_pdu_fdd.vrb_type = 0; - BCCH_alloc_pdu_fdd.rballoc = BCCH_RB_ALLOC; - BCCH_alloc_pdu_fdd.ndi = 1; - BCCH_alloc_pdu_fdd.rv = 1; - BCCH_alloc_pdu_fdd.mcs = 1; - BCCH_alloc_pdu_fdd.harq_pid = 0; - BCCH_alloc_pdu_fdd.TPC = 1; // set to 3 PRB - */ - - DLSCH_alloc_pdu1A.type = 1; - DLSCH_alloc_pdu1A.vrb_type = 0; - DLSCH_alloc_pdu1A.rballoc = BCCH_RB_ALLOC; - DLSCH_alloc_pdu1A.ndi = 1; - DLSCH_alloc_pdu1A.rv = 1; - DLSCH_alloc_pdu1A.mcs = 2; - DLSCH_alloc_pdu1A.harq_pid = 0; - DLSCH_alloc_pdu1A.TPC = 1; // set to 3 PRB - - DLSCH_alloc_pdu1A_fdd.type = 1; - DLSCH_alloc_pdu1A_fdd.vrb_type = 0; - DLSCH_alloc_pdu1A_fdd.rballoc = BCCH_RB_ALLOC; - DLSCH_alloc_pdu1A_fdd.ndi = 1; - DLSCH_alloc_pdu1A_fdd.rv = 1; - DLSCH_alloc_pdu1A_fdd.mcs = 2; - DLSCH_alloc_pdu1A_fdd.harq_pid = 0; - DLSCH_alloc_pdu1A_fdd.TPC = 1; // set to 3 PRB - - RA_alloc_pdu.type = 1; - RA_alloc_pdu.vrb_type = 0; - RA_alloc_pdu.rballoc = RA_RB_ALLOC; - RA_alloc_pdu.ndi = 1; - RA_alloc_pdu.rv = 0; - RA_alloc_pdu.mcs = 0; - RA_alloc_pdu.harq_pid = 0; - RA_alloc_pdu.TPC = 1; - - RA_alloc_pdu_fdd.type = 1; - RA_alloc_pdu_fdd.vrb_type = 0; - RA_alloc_pdu_fdd.rballoc = RA_RB_ALLOC; - RA_alloc_pdu_fdd.ndi = 1; - RA_alloc_pdu_fdd.rv = 1; - RA_alloc_pdu_fdd.mcs = 1; - RA_alloc_pdu_fdd.harq_pid = 0; - RA_alloc_pdu_fdd.TPC = 1; - - - DLSCH_alloc_pdu1.rballoc = 0xf; - DLSCH_alloc_pdu1.TPC = 0; - DLSCH_alloc_pdu1.dai = 0; - DLSCH_alloc_pdu1.harq_pid = 0; - DLSCH_alloc_pdu1.tb_swap = 0; - DLSCH_alloc_pdu1.mcs1 = 4; - DLSCH_alloc_pdu1.ndi1 = 1; - DLSCH_alloc_pdu1.rv1 = 0; - - // Forget second codeword - if (transmission_mode == 6) { - DLSCH_alloc_pdu1.tpmi = 5; // PUSCH_PRECODING0 - } else { - DLSCH_alloc_pdu1.tpmi = 0; - } - - DLSCH_alloc_pdu2.rah = 0; - DLSCH_alloc_pdu2.rballoc = DLSCH_RB_ALLOC; - DLSCH_alloc_pdu2.TPC = 0; - DLSCH_alloc_pdu2.dai = 0; - DLSCH_alloc_pdu2.harq_pid = 0; - DLSCH_alloc_pdu2.tb_swap = 0; - DLSCH_alloc_pdu2.mcs1 = 4; - DLSCH_alloc_pdu2.ndi1 = 1; - DLSCH_alloc_pdu2.rv1 = 0; - - // Forget second codeword - if (transmission_mode == 6) { - DLSCH_alloc_pdu2.tpmi = 5; // PUSCH_PRECODING0 - } else { - DLSCH_alloc_pdu2.tpmi = 0; - } + // init DCI structures for testing + + UL_alloc_pdu.type = 0; + UL_alloc_pdu.hopping = 0; + UL_alloc_pdu.rballoc = UL_RB_ALLOC; + UL_alloc_pdu.mcs = 2; + UL_alloc_pdu.ndi = 1; + UL_alloc_pdu.TPC = 0; + UL_alloc_pdu.cqi_req = 1; + + /* + BCCH_alloc_pdu.type = 1; + BCCH_alloc_pdu.vrb_type = 0; + BCCH_alloc_pdu.rballoc = BCCH_RB_ALLOC; + BCCH_alloc_pdu.ndi = 1; + BCCH_alloc_pdu.rv = 1; + BCCH_alloc_pdu.mcs = 1; + BCCH_alloc_pdu.harq_pid = 0; + BCCH_alloc_pdu.TPC = 1; // set to 3 PRB + + // for FDD mode + BCCH_alloc_pdu_fdd.type = 1; + BCCH_alloc_pdu_fdd.vrb_type = 0; + BCCH_alloc_pdu_fdd.rballoc = BCCH_RB_ALLOC; + BCCH_alloc_pdu_fdd.ndi = 1; + BCCH_alloc_pdu_fdd.rv = 1; + BCCH_alloc_pdu_fdd.mcs = 1; + BCCH_alloc_pdu_fdd.harq_pid = 0; + BCCH_alloc_pdu_fdd.TPC = 1; // set to 3 PRB + */ + + DLSCH_alloc_pdu1A.type = 1; + DLSCH_alloc_pdu1A.vrb_type = 0; + DLSCH_alloc_pdu1A.rballoc = BCCH_RB_ALLOC; + DLSCH_alloc_pdu1A.ndi = 1; + DLSCH_alloc_pdu1A.rv = 1; + DLSCH_alloc_pdu1A.mcs = 2; + DLSCH_alloc_pdu1A.harq_pid = 0; + DLSCH_alloc_pdu1A.TPC = 1; // set to 3 PRB + + DLSCH_alloc_pdu1A_fdd.type = 1; + DLSCH_alloc_pdu1A_fdd.vrb_type = 0; + DLSCH_alloc_pdu1A_fdd.rballoc = BCCH_RB_ALLOC; + DLSCH_alloc_pdu1A_fdd.ndi = 1; + DLSCH_alloc_pdu1A_fdd.rv = 1; + DLSCH_alloc_pdu1A_fdd.mcs = 2; + DLSCH_alloc_pdu1A_fdd.harq_pid = 0; + DLSCH_alloc_pdu1A_fdd.TPC = 1; // set to 3 PRB + + RA_alloc_pdu.type = 1; + RA_alloc_pdu.vrb_type = 0; + RA_alloc_pdu.rballoc = RA_RB_ALLOC; + RA_alloc_pdu.ndi = 1; + RA_alloc_pdu.rv = 0; + RA_alloc_pdu.mcs = 0; + RA_alloc_pdu.harq_pid = 0; + RA_alloc_pdu.TPC = 1; + + RA_alloc_pdu_fdd.type = 1; + RA_alloc_pdu_fdd.vrb_type = 0; + RA_alloc_pdu_fdd.rballoc = RA_RB_ALLOC; + RA_alloc_pdu_fdd.ndi = 1; + RA_alloc_pdu_fdd.rv = 1; + RA_alloc_pdu_fdd.mcs = 1; + RA_alloc_pdu_fdd.harq_pid = 0; + RA_alloc_pdu_fdd.TPC = 1; + + + DLSCH_alloc_pdu1.rballoc = 0xf; + DLSCH_alloc_pdu1.TPC = 0; + DLSCH_alloc_pdu1.dai = 0; + DLSCH_alloc_pdu1.harq_pid = 0; + DLSCH_alloc_pdu1.tb_swap = 0; + DLSCH_alloc_pdu1.mcs1 = 4; + DLSCH_alloc_pdu1.ndi1 = 1; + DLSCH_alloc_pdu1.rv1 = 0; + + // Forget second codeword + if (transmission_mode == 6) { + DLSCH_alloc_pdu1.tpmi = 5; // PUSCH_PRECODING0 + } else { + DLSCH_alloc_pdu1.tpmi = 0; + } + + DLSCH_alloc_pdu2.rah = 0; + DLSCH_alloc_pdu2.rballoc = DLSCH_RB_ALLOC; + DLSCH_alloc_pdu2.TPC = 0; + DLSCH_alloc_pdu2.dai = 0; + DLSCH_alloc_pdu2.harq_pid = 0; + DLSCH_alloc_pdu2.tb_swap = 0; + DLSCH_alloc_pdu2.mcs1 = 4; + DLSCH_alloc_pdu2.ndi1 = 1; + DLSCH_alloc_pdu2.rv1 = 0; + + // Forget second codeword + if (transmission_mode == 6) { + DLSCH_alloc_pdu2.tpmi = 5; // PUSCH_PRECODING0 + } else { + DLSCH_alloc_pdu2.tpmi = 0; + } } diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 83f639a89d4a4451d3a135bca0a77054c01c7e33..fcaab0b80b035ec1bf45f9c19c14fc84857a144a 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -48,66 +48,72 @@ extern RAN_CONTEXT_t RC; -void dl_phy_sync_success(module_id_t module_idP, - frame_t frameP, - unsigned char eNB_index, - uint8_t first_sync) //init as MR +void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) //init as MR { - LOG_D(MAC,"[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", module_idP, frameP, eNB_index); + LOG_D(MAC, "[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", + module_idP, frameP, eNB_index); #if defined(ENABLE_USE_MME) - int mme_enabled=1; + int mme_enabled = 1; #else - int mme_enabled=0; + int mme_enabled = 0; #endif - if (first_sync==1 && !(mme_enabled==1)) { - //layer2_init_UE(module_idP); - openair_rrc_ue_init(module_idP,eNB_index); - } else - { - rrc_in_sync_ind(module_idP,frameP,eNB_index); - } + if (first_sync == 1 && !(mme_enabled == 1)) { + //layer2_init_UE(module_idP); + openair_rrc_ue_init(module_idP, eNB_index); + } else { + rrc_in_sync_ind(module_idP, frameP, eNB_index); + } } -void mac_UE_out_of_sync_ind(module_id_t module_idP, frame_t frameP, uint16_t eNB_index) +void +mac_UE_out_of_sync_ind(module_id_t module_idP, frame_t frameP, + uint16_t eNB_index) { - // Mac_rlc_xface->mac_out_of_sync_ind(Mod_id, frameP, eNB_index); + // Mac_rlc_xface->mac_out_of_sync_ind(Mod_id, frameP, eNB_index); } -int mac_top_init_ue(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active) +int +mac_top_init_ue(int eMBMS_active, char *uecap_xer, + uint8_t cba_group_active, uint8_t HO_active) { - int i; + int i; - LOG_I(MAC,"[MAIN] Init function start:Nb_UE_INST=%d\n",NB_UE_INST); + LOG_I(MAC, "[MAIN] Init function start:Nb_UE_INST=%d\n", NB_UE_INST); - if (NB_UE_INST>0) { - UE_mac_inst = (UE_MAC_INST*)malloc16(NB_UE_INST*sizeof(UE_MAC_INST)); + if (NB_UE_INST > 0) { + UE_mac_inst = + (UE_MAC_INST *) malloc16(NB_UE_INST * sizeof(UE_MAC_INST)); - AssertFatal(UE_mac_inst!=NULL, - "[MAIN] Can't ALLOCATE %zu Bytes for %d UE_MAC_INST with size %zu \n",NB_UE_INST*sizeof(UE_MAC_INST),NB_UE_INST,sizeof(UE_MAC_INST)); + AssertFatal(UE_mac_inst != NULL, + "[MAIN] Can't ALLOCATE %zu Bytes for %d UE_MAC_INST with size %zu \n", + NB_UE_INST * sizeof(UE_MAC_INST), NB_UE_INST, + sizeof(UE_MAC_INST)); - LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d UE_MAC_INST @ %p\n",NB_UE_INST*sizeof(UE_MAC_INST),NB_UE_INST,UE_mac_inst); + LOG_D(MAC, "[MAIN] ALLOCATE %zu Bytes for %d UE_MAC_INST @ %p\n", + NB_UE_INST * sizeof(UE_MAC_INST), NB_UE_INST, UE_mac_inst); - bzero(UE_mac_inst,NB_UE_INST*sizeof(UE_MAC_INST)); + bzero(UE_mac_inst, NB_UE_INST * sizeof(UE_MAC_INST)); - for(i=0; i<NB_UE_INST; i++) { - ue_init_mac(i); + for (i = 0; i < NB_UE_INST; i++) { + ue_init_mac(i); + } + } else { + UE_mac_inst = NULL; } - } else { - UE_mac_inst = NULL; - } - LOG_I(MAC,"[MAIN] calling RRC\n"); - openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active,HO_active); + LOG_I(MAC, "[MAIN] calling RRC\n"); + openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active, + HO_active); - - LOG_I(MAC,"[MAIN][INIT] Init function finished\n"); - return(0); + LOG_I(MAC, "[MAIN][INIT] Init function finished\n"); + + return (0); } @@ -115,183 +121,107 @@ int mac_top_init_ue(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, void mac_top_init_eNB() { - module_id_t i,j; - int list_el; - UE_list_t *UE_list; - eNB_MAC_INST *mac; - - LOG_I(MAC,"[MAIN] Init function start:nb_macrlc_inst=%d\n",RC.nb_macrlc_inst); - - if (RC.nb_macrlc_inst>0) { - RC.mac = (eNB_MAC_INST**)malloc16(RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*)); - AssertFatal(RC.mac != NULL,"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n", - RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*), - RC.nb_macrlc_inst, - sizeof(eNB_MAC_INST)); - for (i=0;i<RC.nb_macrlc_inst;i++) { - RC.mac[i] = (eNB_MAC_INST*)malloc16(sizeof(eNB_MAC_INST)); - AssertFatal(RC.mac != NULL, - "can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n", - RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*),RC.nb_macrlc_inst,sizeof(eNB_MAC_INST)); - LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",sizeof(eNB_MAC_INST),RC.nb_macrlc_inst,RC.mac); - bzero(RC.mac[i],sizeof(eNB_MAC_INST)); - RC.mac[i]->Mod_id = i; - for (j=0;j<MAX_NUM_CCs;j++) { - RC.mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j]; - RC.mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j]; - for (int k=0;k<10;k++) RC.mac[i]->UL_req_tmp[j][k].ul_config_request_body.ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list_tmp[j][k]; - RC.mac[i]->HI_DCI0_req[j].hi_dci0_request_body.hi_dci0_pdu_list = RC.mac[i]->hi_dci0_pdu_list[j]; - RC.mac[i]->TX_req[j].tx_request_body.tx_pdu_list = RC.mac[i]->tx_request_pdu[j]; - RC.mac[i]->ul_handle = 0; - } + module_id_t i, j; + int list_el; + UE_list_t *UE_list; + eNB_MAC_INST *mac; + + LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n", + RC.nb_macrlc_inst); + + if (RC.nb_macrlc_inst > 0) { + RC.mac = + (eNB_MAC_INST **) malloc16(RC.nb_macrlc_inst * + sizeof(eNB_MAC_INST *)); + AssertFatal(RC.mac != NULL, + "can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n", + RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *), + RC.nb_macrlc_inst, sizeof(eNB_MAC_INST)); + for (i = 0; i < RC.nb_macrlc_inst; i++) { + RC.mac[i] = (eNB_MAC_INST *) malloc16(sizeof(eNB_MAC_INST)); + AssertFatal(RC.mac != NULL, + "can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n", + RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *), + RC.nb_macrlc_inst, sizeof(eNB_MAC_INST)); + LOG_D(MAC, + "[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n", + sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, RC.mac); + bzero(RC.mac[i], sizeof(eNB_MAC_INST)); + RC.mac[i]->Mod_id = i; + for (j = 0; j < MAX_NUM_CCs; j++) { + RC.mac[i]->DL_req[j].dl_config_request_body. + dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j]; + RC.mac[i]->UL_req[j].ul_config_request_body. + ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j]; + for (int k = 0; k < 10; k++) + RC.mac[i]->UL_req_tmp[j][k]. + ul_config_request_body.ul_config_pdu_list = + RC.mac[i]->ul_config_pdu_list_tmp[j][k]; + RC.mac[i]->HI_DCI0_req[j]. + hi_dci0_request_body.hi_dci0_pdu_list = + RC.mac[i]->hi_dci0_pdu_list[j]; + RC.mac[i]->TX_req[j].tx_request_body.tx_pdu_list = + RC.mac[i]->tx_request_pdu[j]; + RC.mac[i]->ul_handle = 0; + } + } + + AssertFatal(rlc_module_init() == 0, + "Could not initialize RLC layer\n"); + + // These should be out of here later + pdcp_layer_init(); + + rrc_init_global_param(); + + } else { + RC.mac = NULL; } - AssertFatal(rlc_module_init()==0,"Could not initialize RLC layer\n"); + // Initialize Linked-List for Active UEs + for (i = 0; i < RC.nb_macrlc_inst; i++) { + mac = RC.mac[i]; - // These should be out of here later - pdcp_layer_init (); - rrc_init_global_param(); + mac->if_inst = IF_Module_init(i); - } else { - RC.mac = NULL; - } - - // Initialize Linked-List for Active UEs - for(i=0; i<RC.nb_macrlc_inst; i++) { - mac = RC.mac[i]; + UE_list = &mac->UE_list; + UE_list->num_UEs = 0; + UE_list->head = -1; + UE_list->head_ul = -1; + UE_list->avail = 0; - mac->if_inst = IF_Module_init(i); + for (list_el = 0; list_el < NUMBER_OF_UE_MAX - 1; list_el++) { + UE_list->next[list_el] = list_el + 1; + UE_list->next_ul[list_el] = list_el + 1; + } - UE_list = &mac->UE_list; + UE_list->next[list_el] = -1; + UE_list->next_ul[list_el] = -1; + } - UE_list->num_UEs=0; - UE_list->head=-1; - UE_list->head_ul=-1; - UE_list->avail=0; +} - for (list_el=0; list_el<NUMBER_OF_UE_MAX-1; list_el++) { - UE_list->next[list_el]=list_el+1; - UE_list->next_ul[list_el]=list_el+1; - } +void mac_init_cell_params(int Mod_idP, int CC_idP) +{ - UE_list->next[list_el]=-1; - UE_list->next_ul[list_el]=-1; - } + int j; + UE_TEMPLATE *UE_template; -} + LOG_D(MAC, "[MSC_NEW][FRAME 00000][MAC_eNB][MOD %02d][]\n", Mod_idP); + COMMON_channels_t *cc = &RC.mac[Mod_idP]->common_channels[CC_idP]; -void mac_init_cell_params(int Mod_idP,int CC_idP) { - - int j; - RA_TEMPLATE *RA_template; - UE_TEMPLATE *UE_template; - int size_bytes1,size_bytes2,size_bits1,size_bits2; - - LOG_D(MAC,"[MAIN][eNB %d] CC_id %d initializing RA_template\n",Mod_idP, CC_idP); - LOG_D(MAC, "[MSC_NEW][FRAME 00000][MAC_eNB][MOD %02d][]\n", Mod_idP); - COMMON_channels_t *cc = &RC.mac[Mod_idP]->common_channels[CC_idP]; - - RA_template = (RA_TEMPLATE *)&cc->RA_template[0]; - - for (j=0; j<NB_RA_PROC_MAX; j++) { - if ( cc->tdd_Config != NULL) { - switch (cc->mib->message.dl_Bandwidth) { - case MasterInformationBlock__dl_Bandwidth_n6: - size_bytes1 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); - size_bytes2 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); - size_bits1 = sizeof_DCI1A_1_5MHz_TDD_1_6_t; - size_bits2 = sizeof_DCI1A_1_5MHz_TDD_1_6_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n25: - size_bytes1 = sizeof(DCI1A_5MHz_TDD_1_6_t); - size_bytes2 = sizeof(DCI1A_5MHz_TDD_1_6_t); - size_bits1 = sizeof_DCI1A_5MHz_TDD_1_6_t; - size_bits2 = sizeof_DCI1A_5MHz_TDD_1_6_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n50: - size_bytes1 = sizeof(DCI1A_10MHz_TDD_1_6_t); - size_bytes2 = sizeof(DCI1A_10MHz_TDD_1_6_t); - size_bits1 = sizeof_DCI1A_10MHz_TDD_1_6_t; - size_bits2 = sizeof_DCI1A_10MHz_TDD_1_6_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n100: - size_bytes1 = sizeof(DCI1A_20MHz_TDD_1_6_t); - size_bytes2 = sizeof(DCI1A_20MHz_TDD_1_6_t); - size_bits1 = sizeof_DCI1A_20MHz_TDD_1_6_t; - size_bits2 = sizeof_DCI1A_20MHz_TDD_1_6_t; - break; - - default: - size_bytes1 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); - size_bytes2 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); - size_bits1 = sizeof_DCI1A_1_5MHz_TDD_1_6_t; - size_bits2 = sizeof_DCI1A_1_5MHz_TDD_1_6_t; - break; - } - - } else { - switch (cc->mib->message.dl_Bandwidth) { - case MasterInformationBlock__dl_Bandwidth_n6: - size_bytes1 = sizeof(DCI1A_1_5MHz_FDD_t); - size_bytes2 = sizeof(DCI1A_1_5MHz_FDD_t); - size_bits1 = sizeof_DCI1A_1_5MHz_FDD_t; - size_bits2 = sizeof_DCI1A_1_5MHz_FDD_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n25: - size_bytes1 = sizeof(DCI1A_5MHz_FDD_t); - size_bytes2 = sizeof(DCI1A_5MHz_FDD_t); - size_bits1 = sizeof_DCI1A_5MHz_FDD_t; - size_bits2 = sizeof_DCI1A_5MHz_FDD_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n50: - size_bytes1 = sizeof(DCI1A_10MHz_FDD_t); - size_bytes2 = sizeof(DCI1A_10MHz_FDD_t); - size_bits1 = sizeof_DCI1A_10MHz_FDD_t; - size_bits2 = sizeof_DCI1A_10MHz_FDD_t; - break; - - case MasterInformationBlock__dl_Bandwidth_n100: - size_bytes1 = sizeof(DCI1A_20MHz_FDD_t); - size_bytes2 = sizeof(DCI1A_20MHz_FDD_t); - size_bits1 = sizeof_DCI1A_20MHz_FDD_t; - size_bits2 = sizeof_DCI1A_20MHz_FDD_t; - break; - - default: - size_bytes1 = sizeof(DCI1A_1_5MHz_FDD_t); - size_bytes2 = sizeof(DCI1A_1_5MHz_FDD_t); - size_bits1 = sizeof_DCI1A_1_5MHz_FDD_t; - size_bits2 = sizeof_DCI1A_1_5MHz_FDD_t; - break; - } + memset(&RC.mac[Mod_idP]->eNB_stats, 0, sizeof(eNB_STATS)); + UE_template = + (UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_list.UE_template[CC_idP][0]; + + for (j = 0; j < NUMBER_OF_UE_MAX; j++) { + UE_template[j].rnti = 0; + // initiallize the eNB to UE statistics + memset(&RC.mac[Mod_idP]->UE_list.eNB_UE_stats[CC_idP][j], 0, + sizeof(eNB_UE_STATS)); } - - memcpy((void *)&RA_template[j].RA_alloc_pdu1[0],(void *)&RA_alloc_pdu,size_bytes1); - memcpy((void *)&RA_template[j].RA_alloc_pdu2[0],(void *)&DLSCH_alloc_pdu1A,size_bytes2); - RA_template[j].RA_dci_size_bytes1 = size_bytes1; - RA_template[j].RA_dci_size_bytes2 = size_bytes2; - RA_template[j].RA_dci_size_bits1 = size_bits1; - RA_template[j].RA_dci_size_bits2 = size_bits2; - - RA_template[j].RA_dci_fmt1 = format1A; - RA_template[j].RA_dci_fmt2 = format1A; - } - - memset (&RC.mac[Mod_idP]->eNB_stats,0,sizeof(eNB_STATS)); - UE_template = (UE_TEMPLATE *)&RC.mac[Mod_idP]->UE_list.UE_template[CC_idP][0]; - - for (j=0; j<NUMBER_OF_UE_MAX; j++) { - UE_template[j].rnti=0; - // initiallize the eNB to UE statistics - memset (&RC.mac[Mod_idP]->UE_list.eNB_UE_stats[CC_idP][j],0,sizeof(eNB_UE_STATS)); - } } @@ -300,17 +230,17 @@ int rlcmac_init_global_param(void) { - LOG_I(MAC,"[MAIN] CALLING RLC_MODULE_INIT...\n"); + LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n"); - if (rlc_module_init()!=0) { - return(-1); - } + if (rlc_module_init() != 0) { + return (-1); + } - pdcp_layer_init (); + pdcp_layer_init(); - LOG_I(MAC,"[MAIN] Init Global Param Done\n"); + LOG_I(MAC, "[MAIN] Init Global Param Done\n"); - return 0; + return 0; } @@ -318,29 +248,31 @@ void mac_top_cleanup(void) { #ifndef USER_MODE - pdcp_module_cleanup (); + pdcp_module_cleanup(); #endif - if (NB_UE_INST>0) { - free (UE_mac_inst); - } + if (NB_UE_INST > 0) { + free(UE_mac_inst); + } - if (RC.nb_macrlc_inst>0) { - free(RC.mac); - } + if (RC.nb_macrlc_inst > 0) { + free(RC.mac); + } } -int l2_init_ue(int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active) +int +l2_init_ue(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, + uint8_t HO_active) { - LOG_I(MAC,"[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); - // NB_NODE=2; - // NB_INST=2; - - rlcmac_init_global_param(); - LOG_I(MAC,"[MAIN] init UE MAC functions \n"); - mac_top_init_ue(eMBMS_active,uecap_xer,cba_group_active,HO_active); - return(1); + LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); + // NB_NODE=2; + // NB_INST=2; + + rlcmac_init_global_param(); + LOG_I(MAC, "[MAIN] init UE MAC functions \n"); + mac_top_init_ue(eMBMS_active, uecap_xer, cba_group_active, HO_active); + return (1); } int l2_init_eNB() @@ -348,13 +280,12 @@ int l2_init_eNB() - LOG_I(MAC,"[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); + LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); - rlcmac_init_global_param(); + rlcmac_init_global_param(); - LOG_D(MAC,"[MAIN] ALL INIT OK\n"); + LOG_D(MAC, "[MAIN] ALL INIT OK\n"); - return(1); + return (1); } - diff --git a/openair2/LAYER2/MAC/openair2_proc.c b/openair2/LAYER2/MAC/openair2_proc.c deleted file mode 100644 index ab78be3c61048577790325f1b83d4a5f29af1058..0000000000000000000000000000000000000000 --- a/openair2/LAYER2/MAC/openair2_proc.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* \file openair2_proc.c - \brief MAC layer online statistics - \author Navid Nikaein - \date 2013 - 2014 - \version 1.0 - @ingroup _mac -*/ - -#ifndef USER_MODE -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/proc_fs.h> - -#endif -#include "LAYER2/MAC/defs.h" -#include "LAYER2/MAC/extern.h" -//#include "RRC/LITE/extern.h" -//#include "LAYER2/PDCP/pdcp.h" -#include "proto.h" - -extern RAN_CONTEXT_t RC; - -int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) - -{ - - int len = 0,fg,Overhead, Sign; - unsigned int i,j,k,kk; - unsigned int ue_id, eNB_id; - unsigned int Mod_id = 0,CH_index; - unsigned int stat_tx_pdcp_sdu; - unsigned int stat_tx_pdcp_bytes; - unsigned int stat_tx_pdcp_sdu_discarded; - unsigned int stat_tx_pdcp_bytes_discarded; - unsigned int stat_tx_data_pdu; - unsigned int stat_tx_data_bytes; - unsigned int stat_tx_retransmit_pdu_by_status; - unsigned int stat_tx_retransmit_bytes_by_status; - unsigned int stat_tx_retransmit_pdu; - unsigned int stat_tx_retransmit_bytes; - unsigned int stat_tx_control_pdu; - unsigned int stat_tx_control_bytes; - unsigned int stat_rx_pdcp_sdu; - unsigned int stat_rx_pdcp_bytes; - unsigned int stat_rx_data_pdus_duplicate; - unsigned int stat_rx_data_bytes_duplicate; - unsigned int stat_rx_data_pdu; - unsigned int stat_rx_data_bytes; - unsigned int stat_rx_data_pdu_dropped; - unsigned int stat_rx_data_bytes_dropped; - unsigned int stat_rx_data_pdu_out_of_window; - unsigned int stat_rx_data_bytes_out_of_window; - unsigned int stat_rx_control_pdu; - unsigned int stat_rx_control_bytes; - unsigned int stat_timer_reordering_timed_out; - unsigned int stat_timer_poll_retransmit_timed_out; - unsigned int stat_timer_status_prohibit_timed_out; - - // UE part - for (ue_id=0; ue_id<NUM_UE_INST; ue_id++) { - // mod_id used for PDCP and RLC - Mod_id = NB_eNB_INST + ue_id ; - - len+=sprintf(&buffer[len],"UE RX TTI: %d\n",UE_mac_inst[ue_id].rxFrame); - - for (enb_id= 0; enb_id <NB_SIG_CNX_UE; enb_id++) { - - switch (mac_get_rrc_status(ue_id,0,enb_id) > RRC_CONNECTED) { - case RRC_RECONFIGURED : - case RRC_CONNECTED: - case RRC_SI_RECEIVED: - case RRC_IDLE: - break; - - if (mac_get_rrc_status(ue_id,0,enb_id) > RRC_CONNECTED) { - // if (UE_mac_inst[ue_id].Dcch_lchan[CH_index].Active==1) { - len+=sprintf(&buffer[len],"eNB %d: Wideband SINR %d dB---\n", - CH_index,UE_mac_inst[Mod_id].Def_meas[CH_index].Wideband_sinr); - len+=sprintf(&buffer[len],"CH %d: Subband SINR (dB) :", - CH_index); - - for (fg=0; fg<NUMBER_OF_MEASUREMENT_SUBBANDS; fg++) { - len+=sprintf(&buffer[len],"%d ",UE_mac_inst[Mod_id].Def_meas[CH_index].Sinr_meas[0][fg]); - } - - len+=sprintf(&buffer[len],"\n"); - - - len+=sprintf(&buffer[len],"BCCH %d, NB_RX_MAC = %d (%d errors)\n", - UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.Lchan_id.Index, - UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); - - - - len+=sprintf(&buffer[len],"CCCH %d, NB_RX_MAC = %d (%d errors)\n", - UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.Lchan_id.Index, - UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); - - - len+=sprintf(&buffer[len],"LCHAN %d (DCCH), NB_TX_MAC = %d (%d bits/TTI, %d kbits/sec), NB_RX_MAC = %d (%d errors)\n", - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.Lchan_id.Index, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_TX, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate, - (10*UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate)>>5, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); - - for(i=1; i<NB_RAB_MAX; i++) { - if (UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Active==1) { - Overhead=UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][CH_index][i]; - - if(Overhead<0) { - Overhead=-Overhead; - Sign=-1; - } else { - Sign=1; - } - - len+=sprintf(&buffer[len],"[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s) , LAYER2 TX OVERHEAD: %d Kbits/s\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - Pdcp_stats_tx[k][CH_index][i], - Pdcp_stats_tx_rate[k][CH_index][i], - (10*Pdcp_stats_tx_rate[k][CH_index][i])>>5, - Pdcp_stats_rx[k][CH_index][i], - Pdcp_stats_rx_rate[k][CH_index][i], - (10*Pdcp_stats_rx_rate[k][CH_index][i])>>5, - Sign*(10*Overhead)>>5); - - - int status = rlc_stat_req (k, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - &stat_tx_pdcp_sdu, - &stat_tx_pdcp_bytes, - &stat_tx_pdcp_sdu_discarded, - &stat_tx_pdcp_bytes_discarded, - &stat_tx_data_pdu, - &stat_tx_data_bytes, - &stat_tx_retransmit_pdu_by_status, - &stat_tx_retransmit_bytes_by_status, - &stat_tx_retransmit_pdu, - &stat_tx_retransmit_bytes, - &stat_tx_control_pdu, - &stat_tx_control_bytes, - &stat_rx_pdcp_sdu, - &stat_rx_pdcp_bytes, - &stat_rx_data_pdus_duplicate, - &stat_rx_data_bytes_duplicate, - &stat_rx_data_pdu, - &stat_rx_data_bytes, - &stat_rx_data_pdu_dropped, - &stat_rx_data_bytes_dropped, - &stat_rx_data_pdu_out_of_window, - &stat_rx_data_bytes_out_of_window, - &stat_rx_control_pdu, - &stat_rx_control_bytes, - &stat_timer_reordering_timed_out, - &stat_timer_poll_retransmit_timed_out, - &stat_timer_status_prohibit_timed_out) ; - - if (status == RLC_OP_STATUS_OK) { - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_pdcp_sdu, - tx_pdcp_sdu_discarded, - rx_sdu); - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %d", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_data_pdu, - tx_control_pdu, - tx_retransmit_pdu); - len+=sprintf(&buffer[len],"\tRLC LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_retransmit_pdu_by_status, - tx_retransmit_pdu_unblock); - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - rx_data_pdu, - rx_data_pdu_out_of_window, - rx_error_pdu); - } - - len+=sprintf(&buffer[len],"[MAC]: LCHAN %d, NB_TX_MAC = %d (%d bits/TTI, %d kbits/s), NB_RX_MAC = %d (%d errors)\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate, - (10*UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate)>>5, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS); - len+=sprintf(&buffer[len]," TX per TB: "); - - for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++) { - len+=sprintf(&buffer[len],"%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX_TB[kk]); - } - - len+=sprintf(&buffer[len],"\n"); - len+=sprintf(&buffer[len]," RXerr per TB: "); - - for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++) - len+=sprintf(&buffer[len],"%d/%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS_TB[kk], - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_TB[kk]); - - len+=sprintf(&buffer[len],"\n"); - - - - } - - } - } - } - -#endif //PHY_EMUL_ONE_MACHINE - } - - else if(Mac_rlc_xface->Is_cluster_head[k] ==1) { - - Mod_id=k; - len+=sprintf(&buffer[len], - "-------------------------------------------------------------------CH %d: TTI: %d------------------------------------------------------------------\n", - NODE_ID[Mod_id],Mac_rlc_xface->frame); - - for(i=1; i<=NB_CNX_CH; i++) { - if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) { - len+=sprintf(&buffer[len],"\nMR index %d: DL SINR (feedback) %d dB, CQI: %s\n\n", - i,//CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id[0], - CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr); - //print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi)); - - len+=sprintf(&buffer[len], - "[MAC] LCHAN %d (DCCH), NB_TX_MAC= %d (%d bits/TTI, %d kbits/s), NB_RX_MAC= %d (errors %d, sacch errors %d, sach errors %d, sach_missing %d)\n\n", - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.Lchan_id.Index, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_TX, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate, - (10*CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate)>>5, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACCH_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_MISSING); - - for(j=0; j<NB_RAB_MAX; j++) { - if (CH_mac_inst[Mod_id].Dtch_lchan[j][i].Active==1) { - Overhead=CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][i][j]; - - if(Overhead<0) { - Overhead=-Overhead; - Sign=-1; - } else { - Sign=1; - } - - len+=sprintf(&buffer[len], - "[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s), LAYER2 TX OVERHEAD= %d Kbits/s\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - Pdcp_stats_tx[k][i][j], - Pdcp_stats_tx_rate[k][i][j], - (10*Pdcp_stats_tx_rate[k][i][j])>>5, - Pdcp_stats_rx[k][i][j], - Pdcp_stats_rx_rate[k][i][j], - (10*Pdcp_stats_rx_rate[k][i][j])>>5, - Sign*(10*Overhead)>>5); - int status = rlc_stat_req (k, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - &tx_pdcp_sdu, - &tx_pdcp_sdu_discarded, - &tx_retransmit_pdu_unblock, - &tx_retransmit_pdu_by_status, - &tx_retransmit_pdu, - &tx_data_pdu, - &tx_control_pdu, - &rx_sdu, - &rx_error_pdu, - &rx_data_pdu, - &rx_data_pdu_out_of_window, - &rx_control_pdu) ; - /* - if (status == RLC_OP_STATUS_OK) { - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_pdcp_sdu, - tx_pdcp_sdu_discarded, - rx_sdu); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_data_pdu, - tx_control_pdu, - tx_retransmit_pdu); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_retransmit_pdu_by_status, - tx_retransmit_pdu_unblock); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - rx_data_pdu, - rx_data_pdu_out_of_window, - rx_error_pdu); - } - */ - len+=sprintf(&buffer[len], - "[MAC]LCHAN %d (CNX %d,RAB %d), NB_TX_MAC= %d (%d bits/TTI, %d kbit/s), NB_RX_MAC= %d (errors %d, sacch_errors %d, sach_errors %d, sach_missing %d)\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - i,j, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate, - (10*CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate)>>5, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACCH_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_MISSING); - len+=sprintf(&buffer[len],"[MAC][SCHEDULER] TX Arrival Rate %d, TX Service Rate %d, RX Arrival rate %d, RX Service rate %d, NB_BW_REQ_RX %d\n\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Arrival_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Tx_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Req_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Rx_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_BW_REQ_RX); - - /* - len+=sprintf(&buffer[len]," TX per TB: "); - for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++) - len+=sprintf(&buffer[len],"%d.",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX_TB[kk]); - len+=sprintf(&buffer[len],"\n"); - len+=sprintf(&buffer[len]," RXerr per TB: "); - for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++) - len+=sprintf(&buffer[len],"%d/%d . ",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS_TB[kk], - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_TB[kk]); - len+=sprintf(&buffer[len],"\n"); - */ - } - } - } - } - - } - } - - return len; -} - -#ifndef USER_MODE -static struct proc_dir_entry *proc_openair2_root; -/* - * Initialize the module and add the /proc file. - */ -int add_openair2_stats() -{ - //#ifdef KERNEL_VERSION_GREATER_THAN_2629 - struct proc_dir_entry *pde; - //#endif - - proc_openair2_root = proc_mkdir("openair2",0); - //#ifdef KERNEL_VERSION_GREATER_THAN_2629 - // pde = proc_create_entry("lchan_stats", S_IFREG | S_IRUGO, proc_openair2_root); - pde = create_proc_read_entry("lchan_stats", S_IFREG | S_IRUGO, proc_openair2_root, (read_proc_t*)&openair2_stats_read, NULL); - - if (!pde) { - printk("[OPENAIR][ERROR] can't create proc entry !\n"); - } - - //#else - //create_proc_info_entry("lchan_stats", S_IFREG | S_IRUGO, proc_openair2_root, openair2_stats_read); - //#endif - - return 0; -} -/* - * Unregister the file when the module is closed. - */ -void remove_openair2_stats() -{ - - if (proc_openair2_root) { - printk("[OPENAIR][CLEANUP] Removing openair proc entry\n"); - remove_proc_entry("lchan_stats", proc_openair2_root); - //#ifdef KERNEL_VERSION_GREATER_THAN_2629 - - //#else - remove_proc_entry("openair2",NULL); - //#endif; - } -} -#endif diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 612f64fe61c2f991fc24944d1debe28da7e0aafb..23d3f3bd603770684c0b2c4364d5f59e609e9668 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -95,389 +95,458 @@ int phy_stats_exist(module_id_t Mod_id, int rnti) */ // This function stores the downlink buffer for all the logical channels -void store_dlsch_buffer (module_id_t Mod_id, - frame_t frameP, - sub_frame_t subframeP) +void +store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, + sub_frame_t subframeP) { - int UE_id,i; - rnti_t rnti; - mac_rlc_status_resp_t rlc_status; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_TEMPLATE *UE_template; + int UE_id, i; + rnti_t rnti; + mac_rlc_status_resp_t rlc_status; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_TEMPLATE *UE_template; - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id]; - - // clear logical channel interface variables - UE_template->dl_buffer_total = 0; - UE_template->dl_pdus_total = 0; + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; - for(i=0; i< MAX_NUM_LCID; i++) { - UE_template->dl_buffer_info[i]=0; - UE_template->dl_pdus_in_buffer[i]=0; - UE_template->dl_buffer_head_sdu_creation_time[i]=0; - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i]=0; - } + UE_template = + &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; - rnti = UE_RNTI(Mod_id,UE_id); + // clear logical channel interface variables + UE_template->dl_buffer_total = 0; + UE_template->dl_pdus_total = 0; - for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels + for (i = 0; i < MAX_NUM_LCID; i++) { + UE_template->dl_buffer_info[i] = 0; + UE_template->dl_pdus_in_buffer[i] = 0; + UE_template->dl_buffer_head_sdu_creation_time[i] = 0; + UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = 0; + } - rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); - UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel - UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; - UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; - UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max, - rlc_status.head_sdu_creation_time ); - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send; - UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented; - UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer - UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[i]; + rnti = UE_RNTI(Mod_id, UE_id); + + for (i = 0; i < MAX_NUM_LCID; i++) { // loop over all the logical channels + + rlc_status = + mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP, + ENB_FLAG_YES, MBMS_FLAG_NO, i, 0); + UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel + UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; + UE_template->dl_buffer_head_sdu_creation_time[i] = + rlc_status.head_sdu_creation_time; + UE_template->dl_buffer_head_sdu_creation_time_max = + cmax(UE_template->dl_buffer_head_sdu_creation_time_max, + rlc_status.head_sdu_creation_time); + UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = + rlc_status.head_sdu_remaining_size_to_send; + UE_template->dl_buffer_head_sdu_is_segmented[i] = + rlc_status.head_sdu_is_segmented; + UE_template->dl_buffer_total += UE_template->dl_buffer_info[i]; //storing the total dlsch buffer + UE_template->dl_pdus_total += + UE_template->dl_pdus_in_buffer[i]; #ifdef DEBUG_eNB_SCHEDULER - /* note for dl_buffer_head_sdu_remaining_size_to_send[i] : - * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent - */ - if (UE_template->dl_buffer_info[i]>0) - LOG_D(MAC, - "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", - Mod_id, frameP, subframeP, UE_id, - i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i], - UE_template->dl_buffer_head_sdu_creation_time[i], - UE_template->dl_buffer_head_sdu_remaining_size_to_send[i], - UE_template->dl_buffer_head_sdu_is_segmented[i] - ); + /* note for dl_buffer_head_sdu_remaining_size_to_send[i] : + * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent + */ + if (UE_template->dl_buffer_info[i] > 0) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", + Mod_id, frameP, subframeP, UE_id, + i, UE_template->dl_pdus_in_buffer[i], + UE_template->dl_buffer_info[i], + UE_template->dl_buffer_head_sdu_creation_time[i], + UE_template-> + dl_buffer_head_sdu_remaining_size_to_send[i], + UE_template->dl_buffer_head_sdu_is_segmented[i]); #endif - } + } - //#ifdef DEBUG_eNB_SCHEDULER - if ( UE_template->dl_buffer_total>0) - LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n", - Mod_id, frameP, subframeP, UE_id, - UE_template->dl_buffer_total, - UE_template->dl_pdus_total - ); + //#ifdef DEBUG_eNB_SCHEDULER + if (UE_template->dl_buffer_total > 0) + LOG_D(MAC, + "[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n", + Mod_id, frameP, subframeP, UE_id, + UE_template->dl_buffer_total, + UE_template->dl_pdus_total); - //#endif - } + //#endif + } } // This function returns the estimated number of RBs required by each UE for downlink scheduling -void assign_rbs_required (module_id_t Mod_id, - frame_t frameP, - sub_frame_t subframe, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - int min_rb_unit[MAX_NUM_CCs]) +void +assign_rbs_required(module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t + nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + int min_rb_unit[MAX_NUM_CCs]) { - uint16_t TBS = 0; - - int UE_id,n,i,j,CC_id,pCCid,tmp; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - eNB_UE_STATS *eNB_UE_stats,*eNB_UE_stats_i,*eNB_UE_stats_j; - int N_RB_DL; - - // clear rb allocations across all CC_id - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - pCCid = UE_PCCID(Mod_id,UE_id); - - //update CQI information across component carriers - for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) { + uint16_t TBS = 0; - CC_id = UE_list->ordered_CCids[n][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + int UE_id, n, i, j, CC_id, pCCid, tmp; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; + int N_RB_DL; - eNB_UE_stats->dlsch_mcs1=cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - - } - - // provide the list of CCs sorted according to MCS - for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) { - eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id]; - for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) { - DevAssert( j < MAX_NUM_CCs ); - eNB_UE_stats_j = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; - if (eNB_UE_stats_j->dlsch_mcs1 > - eNB_UE_stats_i->dlsch_mcs1) { - tmp = UE_list->ordered_CCids[i][UE_id]; - UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; - UE_list->ordered_CCids[j][UE_id] = tmp; - } - } - } - - if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) { - LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id); - - for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - - if (eNB_UE_stats->dlsch_mcs1==0) { - nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small - } else { - nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; - } + // clear rb allocations across all CC_id + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]); + pCCid = UE_PCCID(Mod_id, UE_id); - LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", - UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total, - nb_rbs_required[CC_id][UE_id],eNB_UE_stats->dlsch_mcs1,TBS); + //update CQI information across component carriers + for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + CC_id = UE_list->ordered_CCids[n][UE_id]; + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - /* calculating required number of RBs for each UE */ - while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; + eNB_UE_stats->dlsch_mcs1 = + cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,N_RB_DL); - nb_rbs_required[CC_id][UE_id] = N_RB_DL; - break; - } + } - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]); - } // end of while + // provide the list of CCs sorted according to MCS + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + eNB_UE_stats_i = + &UE_list->eNB_UE_stats[UE_list-> + ordered_CCids[i][UE_id]][UE_id]; + for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { + DevAssert(j < MAX_NUM_CCs); + eNB_UE_stats_j = + &UE_list-> + eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; + if (eNB_UE_stats_j->dlsch_mcs1 > + eNB_UE_stats_i->dlsch_mcs1) { + tmp = UE_list->ordered_CCids[i][UE_id]; + UE_list->ordered_CCids[i][UE_id] = + UE_list->ordered_CCids[j][UE_id]; + UE_list->ordered_CCids[j][UE_id] = tmp; + } + } + } - LOG_D(MAC,"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - Mod_id, frameP,UE_id, CC_id, min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats->dlsch_mcs1); - } + if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { + LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); + + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + CC_id = UE_list->ordered_CCids[i][UE_id]; + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + + if (eNB_UE_stats->dlsch_mcs1 == 0) { + nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small + } else { + nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; + } + + TBS = + get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rbs_required[CC_id][UE_id]); + + LOG_D(MAC, + "[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", + UE_id, CC_id, + UE_list->UE_template[pCCid][UE_id].dl_buffer_total, + nb_rbs_required[CC_id][UE_id], + eNB_UE_stats->dlsch_mcs1, TBS); + + N_RB_DL = + to_prb(RC.mac[Mod_id]->common_channels[CC_id]. + mib->message.dl_Bandwidth); + + /* calculating required number of RBs for each UE */ + while (TBS < + UE_list->UE_template[pCCid][UE_id]. + dl_buffer_total) { + nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; + + if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { + TBS = + get_TBS_DL(eNB_UE_stats->dlsch_mcs1, N_RB_DL); + nb_rbs_required[CC_id][UE_id] = N_RB_DL; + break; + } + + TBS = + get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rbs_required[CC_id][UE_id]); + } // end of while + + LOG_D(MAC, + "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", + Mod_id, frameP, UE_id, CC_id, min_rb_unit[CC_id], + nb_rbs_required[CC_id][UE_id], TBS, + eNB_UE_stats->dlsch_mcs1); + } + } } - } } // This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes -int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag ) +int +maxround(module_id_t Mod_id, uint16_t rnti, int frame, + sub_frame_t subframe, uint8_t ul_flag) { - uint8_t round,round_max=0,UE_id; - int CC_id,harq_pid; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - COMMON_channels_t *cc; + uint8_t round, round_max = 0, UE_id; + int CC_id, harq_pid; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + COMMON_channels_t *cc; - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - cc = &RC.mac[Mod_id]->common_channels[CC_id]; + cc = &RC.mac[Mod_id]->common_channels[CC_id]; - UE_id = find_UE_id(Mod_id,rnti); - if (cc->tdd_Config) harq_pid = ((frame*10)+subframe)%10; - else harq_pid = ((frame*10)+subframe)&7; + UE_id = find_UE_id(Mod_id, rnti); + if (cc->tdd_Config) + harq_pid = ((frame * 10) + subframe) % 10; + else + harq_pid = ((frame * 10) + subframe) & 7; - round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - if (round > round_max) { - round_max = round; + round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; + if (round > round_max) { + round_max = round; + } } - } - return round_max; + return round_max; } // This function scans all CC_ids for a particular UE to find the maximum DL CQI // it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL) -int maxcqi(module_id_t Mod_id,int32_t UE_id) +int maxcqi(module_id_t Mod_id, int32_t UE_id) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int CC_id,n; - int CQI = 0; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + int CC_id, n; + int CQI = 0; - for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; + for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { + CC_id = UE_list->ordered_CCids[n][UE_id]; - if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) { - CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) { + CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + } } - } - return CQI; + return CQI; } struct sort_ue_dl_params { - int Mod_idP; - int frameP; - int subframeP; + int Mod_idP; + int frameP; + int subframeP; }; static int ue_dl_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_dl_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list; - - int UE_id1 = *(const int *)_a; - int UE_id2 = *(const int *)_b; - - int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); - int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); - int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, 1); - - int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); - int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); - int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, 1); - - int cqi1 = maxcqi(params->Mod_idP, UE_id1); - int cqi2 = maxcqi(params->Mod_idP, UE_id2); - - if (round1 > round2) return -1; - if (round1 < round2) return 1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return -1; - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return 1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return -1; - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return 1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return -1; - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return 1; - - if (cqi1 > cqi2) return -1; - if (cqi1 < cqi2) return 1; - - return 0; + struct sort_ue_dl_params *params = _params; + UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list; + + int UE_id1 = *(const int *) _a; + int UE_id2 = *(const int *) _b; + + int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); + int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); + int round1 = + maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, + 1); + + int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); + int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); + int round2 = + maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, + 1); + + int cqi1 = maxcqi(params->Mod_idP, UE_id1); + int cqi2 = maxcqi(params->Mod_idP, UE_id2); + + if (round1 > round2) + return -1; + if (round1 < round2) + return 1; + + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] > + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) + return -1; + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) + return 1; + + if (UE_list-> + UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max > + UE_list-> + UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) + return -1; + if (UE_list-> + UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < + UE_list-> + UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) + return 1; + + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total > + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) + return -1; + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) + return 1; + + if (cqi1 > cqi2) + return -1; + if (cqi1 < cqi2) + return 1; + + return 0; #if 0 - /* The above order derives from the following. */ - if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (round2 == round1) { - // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. - // for(j=0;j<MAX_NUM_LCID;j++){ - // if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] < - // eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){ - - // first check the buffer status for SRB1 and SRB2 - - if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) < - (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (cqi1 < cqi2) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } - } + /* The above order derives from the following. */ + if (round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (round2 == round1) { + // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. + // for(j=0;j<MAX_NUM_LCID;j++){ + // if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] < + // eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){ + + // first check the buffer status for SRB1 and SRB2 + + if ((UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) < + (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (UE_list->UE_template[pCC_id1] + [UE_id1].dl_buffer_head_sdu_creation_time_max < + UE_list->UE_template[pCC_id2] + [UE_id2].dl_buffer_head_sdu_creation_time_max) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (cqi1 < cqi2) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } + } #endif } // This fuction sorts the UE in order their dlsch buffer and CQI -void sort_UEs (module_id_t Mod_idP, - int frameP, - sub_frame_t subframeP) +void sort_UEs(module_id_t Mod_idP, int frameP, sub_frame_t subframeP) { - int i; - int list[NUMBER_OF_UE_MAX]; - int list_size = 0; - int rnti; - struct sort_ue_dl_params params = { Mod_idP, frameP, subframeP }; + int i; + int list[NUMBER_OF_UE_MAX]; + int list_size = 0; + int rnti; + struct sort_ue_dl_params params = { Mod_idP, frameP, subframeP }; - UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; + UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i]==FALSE) continue; - if ((rnti = UE_RNTI(Mod_idP, i)) == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (UE_list->active[i] == FALSE) + continue; + if ((rnti = UE_RNTI(Mod_idP, i)) == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; - list[list_size] = i; - list_size++; - } + list[list_size] = i; + list_size++; + } - qsort_r(list, list_size, sizeof(int), ue_dl_compare, ¶ms); + qsort_r(list, list_size, sizeof(int), ue_dl_compare, ¶ms); - if (list_size) { - for (i = 0; i < list_size-1; i++) - UE_list->next[list[i]] = list[i+1]; - UE_list->next[list[list_size-1]] = -1; - UE_list->head = list[0]; - } else { - UE_list->head = -1; - } + if (list_size) { + for (i = 0; i < list_size - 1; i++) + UE_list->next[list[i]] = list[i + 1]; + UE_list->next[list[list_size - 1]] = -1; + UE_list->head = list[0]; + } else { + UE_list->head = -1; + } #if 0 - int UE_id1,UE_id2; - int pCC_id1,pCC_id2; - int cqi1,cqi2,round1,round2; - int i=0,ii=0;//,j=0; - rnti_t rnti1,rnti2; - - UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; - - for (i=UE_list->head; i>=0; i=UE_list->next[i]) { - - for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) { - - UE_id1 = i; - rnti1 = UE_RNTI(Mod_idP,UE_id1); - if(rnti1 == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1) - continue; - pCC_id1 = UE_PCCID(Mod_idP,UE_id1); - cqi1 = maxcqi(Mod_idP,UE_id1); // - round1 = maxround(Mod_idP,rnti1,frameP,subframeP,0); - - UE_id2 = ii; - rnti2 = UE_RNTI(Mod_idP,UE_id2); - if(rnti2 == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) - continue; - cqi2 = maxcqi(Mod_idP,UE_id2); - round2 = maxround(Mod_idP,rnti2,frameP,subframeP,0); //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0); - pCC_id2 = UE_PCCID(Mod_idP,UE_id2); - - if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (round2 == round1) { - // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. - // for(j=0;j<MAX_NUM_LCID;j++){ - // if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] < - // eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){ - - // first check the buffer status for SRB1 and SRB2 - - if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) < - (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total ) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if (cqi1 < cqi2) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } - } + int UE_id1, UE_id2; + int pCC_id1, pCC_id2; + int cqi1, cqi2, round1, round2; + int i = 0, ii = 0; //,j=0; + rnti_t rnti1, rnti2; + + UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; + + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + + for (ii = UE_list->next[i]; ii >= 0; ii = UE_list->next[ii]) { + + UE_id1 = i; + rnti1 = UE_RNTI(Mod_idP, UE_id1); + if (rnti1 == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1) + continue; + pCC_id1 = UE_PCCID(Mod_idP, UE_id1); + cqi1 = maxcqi(Mod_idP, UE_id1); // + round1 = maxround(Mod_idP, rnti1, frameP, subframeP, 0); + + UE_id2 = ii; + rnti2 = UE_RNTI(Mod_idP, UE_id2); + if (rnti2 == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) + continue; + cqi2 = maxcqi(Mod_idP, UE_id2); + round2 = maxround(Mod_idP, rnti2, frameP, subframeP, 0); //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0); + pCC_id2 = UE_PCCID(Mod_idP, UE_id2); + + if (round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (round2 == round1) { + // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. + // for(j=0;j<MAX_NUM_LCID;j++){ + // if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] < + // eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){ + + // first check the buffer status for SRB1 and SRB2 + + if ((UE_list->UE_template[pCC_id1][UE_id1]. + dl_buffer_info[1] + + UE_list->UE_template[pCC_id1][UE_id1]. + dl_buffer_info[2]) < + (UE_list->UE_template[pCC_id2][UE_id2]. + dl_buffer_info[1] + + UE_list->UE_template[pCC_id2][UE_id2]. + dl_buffer_info[2])) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (UE_list->UE_template[pCC_id1] + [UE_id1].dl_buffer_head_sdu_creation_time_max < + UE_list->UE_template[pCC_id2] + [UE_id2].dl_buffer_head_sdu_creation_time_max) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (UE_list->UE_template[pCC_id1][UE_id1]. + dl_buffer_total < + UE_list->UE_template[pCC_id2][UE_id2]. + dl_buffer_total) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } else if (cqi1 < cqi2) { + swap_UEs(UE_list, UE_id1, UE_id2, 0); + } + } + } } - } #endif } @@ -485,1050 +554,1297 @@ void sort_UEs (module_id_t Mod_idP, // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done -void dlsch_scheduler_pre_processor (module_id_t Mod_id, - frame_t frameP, - sub_frame_t subframeP, - int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag) +void +dlsch_scheduler_pre_processor(module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframeP, + int N_RBG[MAX_NUM_CCs], int *mbsfn_flag) { - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,round=0,total_ue_count; - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; - int UE_id, i; - uint16_t ii,j; - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - uint16_t average_rbs_per_user[MAX_NUM_CCs] = {0}; - rnti_t rnti; - int min_rb_unit[MAX_NUM_CCs]; - uint16_t r1=0; - uint8_t CC_id; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - - int N_RB_DL; - int transmission_mode = 0; - UE_sched_ctrl *ue_sched_ctl; - // int rrc_status = RRC_IDLE; - COMMON_channels_t *cc; + unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], harq_pid = + 0, round = 0, total_ue_count; + unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; + int UE_id, i; + uint16_t ii, j; + uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; + uint16_t average_rbs_per_user[MAX_NUM_CCs] = { 0 }; + rnti_t rnti; + int min_rb_unit[MAX_NUM_CCs]; + uint16_t r1 = 0; + uint8_t CC_id; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + + int N_RB_DL; + int transmission_mode = 0; + UE_sched_ctrl *ue_sched_ctl; + // int rrc_status = RRC_IDLE; + COMMON_channels_t *cc; #ifdef TM5 - int harq_pid1=0; - int round1=0,round2=0; - int UE_id2; - uint16_t i1,i2,i3; - rnti_t rnti1,rnti2; - LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; - LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; - UE_sched_ctrl *ue_sched_ctl1,*ue_sched_ctl2; + int harq_pid1 = 0; + int round1 = 0, round2 = 0; + int UE_id2; + uint16_t i1, i2, i3; + rnti_t rnti1, rnti2; + LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; + LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; + UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2; #endif - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - if (mbsfn_flag[CC_id]>0) // If this CC is allocated for MBSFN skip it here - continue; + if (mbsfn_flag[CC_id] > 0) // If this CC is allocated for MBSFN skip it here + continue; - min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id); + min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) continue; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) + continue; - UE_id = i; - // Initialize scheduling information for all active UEs - + UE_id = i; + // Initialize scheduling information for all active UEs - dlsch_scheduler_pre_processor_reset(Mod_id, - UE_id, - CC_id, - frameP, - subframeP, - N_RBG[CC_id], - nb_rbs_required, - nb_rbs_required_remaining, - rballoc_sub, - MIMO_mode_indicator); - } - } + dlsch_scheduler_pre_processor_reset(Mod_id, + UE_id, + CC_id, + frameP, + subframeP, + N_RBG[CC_id], + nb_rbs_required, + nb_rbs_required_remaining, + rballoc_sub, + MIMO_mode_indicator); + } + } - // Store the DLSCH buffer for each logical channel - store_dlsch_buffer (Mod_id,frameP,subframeP); + // Store the DLSCH buffer for each logical channel + store_dlsch_buffer(Mod_id, frameP, subframeP); - // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit); + // Calculate the number of RBs required by each UE on the basis of logical channel's buffer + assign_rbs_required(Mod_id, frameP, subframeP, nb_rbs_required, + min_rb_unit); - // Sorts the user on the basis of dlsch logical channel buffer and CQI - sort_UEs (Mod_id,frameP,subframeP); + // Sorts the user on the basis of dlsch logical channel buffer and CQI + sort_UEs(Mod_id, frameP, subframeP); - total_ue_count =0; - // loop over all active UEs - for (i=UE_list->head; i>=0; i=UE_list->next[i]) { - rnti = UE_RNTI(Mod_id,i); + total_ue_count = 0; - if(rnti == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - UE_id = i; + // loop over all active UEs + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + rnti = UE_RNTI(Mod_id, i); - for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - cc=&RC.mac[Mod_id]->common_channels[ii]; - if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10; - else harq_pid = ((frameP*10)+subframeP)&7; - round = ue_sched_ctl->round[CC_id][harq_pid]; + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + UE_id = i; - average_rbs_per_user[CC_id]=0; + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + cc = &RC.mac[Mod_id]->common_channels[ii]; + if (cc->tdd_Config) + harq_pid = ((frameP * 10) + subframeP) % 10; + else + harq_pid = ((frameP * 10) + subframeP) & 7; + round = ue_sched_ctl->round[CC_id][harq_pid]; + average_rbs_per_user[CC_id] = 0; - if(round != 8) { - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - } - //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id]; - if (nb_rbs_required[CC_id][UE_id] > 0) { - total_ue_count = total_ue_count + 1; - } + if (round != 8) { + nb_rbs_required[CC_id][UE_id] = + UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + } + //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id]; + if (nb_rbs_required[CC_id][UE_id] > 0) { + total_ue_count = total_ue_count + 1; + } + // hypothetical assignment + /* + * If schedule is enabled and if the priority of the UEs is modified + * The average rbs per logical channel per user will depend on the level of + * priority. Concerning the hypothetical assignement, we should assign more + * rbs to prioritized users. Maybe, we can do a mapping between the + * average rbs per user and the level of priority or multiply the average rbs + * per user by a coefficient which represents the degree of priority. + */ + + N_RB_DL = + to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib-> + message.dl_Bandwidth); + + if (total_ue_count == 0) { + average_rbs_per_user[CC_id] = 0; + } else if ((min_rb_unit[CC_id] * total_ue_count) <= (N_RB_DL)) { + average_rbs_per_user[CC_id] = + (uint16_t) floor(N_RB_DL / total_ue_count); + } else { + average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE + } + } + } + // note: nb_rbs_required is assigned according to total_buffer_dl + // extend nb_rbs_required to capture per LCID RB required + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + rnti = UE_RNTI(Mod_id, i); - // hypothetical assignment - /* - * If schedule is enabled and if the priority of the UEs is modified - * The average rbs per logical channel per user will depend on the level of - * priority. Concerning the hypothetical assignement, we should assign more - * rbs to prioritized users. Maybe, we can do a mapping between the - * average rbs per user and the level of priority or multiply the average rbs - * per user by a coefficient which represents the degree of priority. - */ + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + for (ii = 0; ii < UE_num_active_CC(UE_list, i); ii++) { + CC_id = UE_list->ordered_CCids[ii][i]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[i]; + round = ue_sched_ctl->round[CC_id][harq_pid]; + + // control channel or retransmission + /* TODO: do we have to check for retransmission? */ + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED + || round > 0) { + nb_rbs_required_remaining_1[CC_id][i] = + nb_rbs_required[CC_id][i]; + } else { + nb_rbs_required_remaining_1[CC_id][i] = + cmin(average_rbs_per_user[CC_id], + nb_rbs_required[CC_id][i]); - if (total_ue_count == 0) { - average_rbs_per_user[CC_id] = 0; - } else if( (min_rb_unit[CC_id] * total_ue_count) <= (N_RB_DL) ) { - average_rbs_per_user[CC_id] = (uint16_t) floor(N_RB_DL/total_ue_count); - } else { - average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE - } + } + } } - } - // note: nb_rbs_required is assigned according to total_buffer_dl - // extend nb_rbs_required to capture per LCID RB required - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - rnti = UE_RNTI(Mod_id,i); - - if(rnti == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) { - CC_id = UE_list->ordered_CCids[ii][i]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[i]; - round = ue_sched_ctl->round[CC_id][harq_pid]; - - // control channel or retransmission - /* TODO: do we have to check for retransmission? */ - if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED || round > 0) { - nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i]; - } else { - nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]); - - } - } - } + //Allocation to UEs is done in 2 rounds, + // 1st stage: average number of RBs allocated to each UE + // 2nd stage: remaining RBs are allocated to high priority UEs + for (r1 = 0; r1 < 2; r1++) { + + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + for (ii = 0; ii < UE_num_active_CC(UE_list, i); ii++) { + CC_id = UE_list->ordered_CCids[ii][i]; + + if (r1 == 0) { + nb_rbs_required_remaining[CC_id][i] = + nb_rbs_required_remaining_1[CC_id][i]; + } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round + nb_rbs_required_remaining[CC_id][i] = + nb_rbs_required[CC_id][i] - + nb_rbs_required_remaining_1[CC_id][i] + + nb_rbs_required_remaining[CC_id][i]; + if (nb_rbs_required_remaining[CC_id][i] < 0) + abort(); + } + + if (nb_rbs_required[CC_id][i] > 0) + LOG_D(MAC, + "round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", + r1, CC_id, i, + nb_rbs_required_remaining[CC_id][i], + nb_rbs_required_remaining_1[CC_id][i], + nb_rbs_required[CC_id][i], + UE_list->UE_sched_ctrl[i]. + pre_nb_available_rbs[CC_id], N_RBG[CC_id], + min_rb_unit[CC_id]); - //Allocation to UEs is done in 2 rounds, - // 1st stage: average number of RBs allocated to each UE - // 2nd stage: remaining RBs are allocated to high priority UEs - for(r1=0; r1<2; r1++) { - - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) { - CC_id = UE_list->ordered_CCids[ii][i]; - - if(r1 == 0) { - nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i]; - } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round - nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i]; -if (nb_rbs_required_remaining[CC_id][i]<0) abort(); - } - - if (nb_rbs_required[CC_id][i]> 0 ) - LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", - r1, CC_id, i, - nb_rbs_required_remaining[CC_id][i], - nb_rbs_required_remaining_1[CC_id][i], - nb_rbs_required[CC_id][i], - UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); - - } - } + } + } - if (total_ue_count > 0 ) { - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - UE_id = i; + if (total_ue_count > 0) { + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + UE_id = i; + + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + round = ue_sched_ctl->round[CC_id][harq_pid]; + + rnti = UE_RNTI(Mod_id, UE_id); + + // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti ); + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + continue; + + transmission_mode = get_tmode(Mod_id, CC_id, UE_id); + // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0); + //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti); + /* 1st allocate for the retx */ + + // retransmission in data channels + // control channel in the 1st transmission + // data channel for all TM + LOG_T(MAC, + "calling dlsch_scheduler_pre_processor_allocate .. \n "); + dlsch_scheduler_pre_processor_allocate(Mod_id, UE_id, + CC_id, + N_RBG[CC_id], + transmission_mode, + min_rb_unit + [CC_id], + to_prb(RC.mac + [Mod_id]->common_channels + [CC_id].mib->message.dl_Bandwidth), + nb_rbs_required, + nb_rbs_required_remaining, + rballoc_sub, + MIMO_mode_indicator); - for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - round = ue_sched_ctl->round[CC_id][harq_pid]; +#ifdef TM5 - rnti = UE_RNTI(Mod_id,UE_id); + // data chanel TM5: to be revisted + if ((round == 0) && + (transmission_mode == 5) && + (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { + + for (j = 0; j < N_RBG[CC_id]; j += 2) { + + if ((((j == (N_RBG[CC_id] - 1)) + && (rballoc_sub[CC_id][j] == 0) + && (ue_sched_ctl-> + rballoc_sub_UE[CC_id][j] == 0)) + || ((j < (N_RBG[CC_id] - 1)) + && (rballoc_sub[CC_id][j + 1] == 0) + && + (ue_sched_ctl->rballoc_sub_UE + [CC_id][j + 1] == 0))) + && (nb_rbs_required_remaining[CC_id][UE_id] + > 0)) { + + for (ii = UE_list->next[i + 1]; ii >= 0; + ii = UE_list->next[ii]) { + + UE_id2 = ii; + rnti2 = UE_RNTI(Mod_id, UE_id2); + ue_sched_ctl2 = + &UE_list->UE_sched_ctrl[UE_id2]; + round2 = ue_sched_ctl2->round[CC_id]; + if (rnti2 == NOT_A_RNTI) + continue; + if (UE_list-> + UE_sched_ctrl + [UE_id2].ul_out_of_sync == 1) + continue; + + eNB_UE_stats2 = + UE_list-> + eNB_UE_stats[CC_id][UE_id2]; + //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); + + if ((mac_eNB_get_rrc_status + (Mod_id, + rnti2) >= RRC_RECONFIGURED) + && (round2 == 0) + && + (get_tmode(Mod_id, CC_id, UE_id2) + == 5) + && (ue_sched_ctl-> + dl_pow_off[CC_id] != 1)) { + + if ((((j == (N_RBG[CC_id] - 1)) + && + (ue_sched_ctl->rballoc_sub_UE + [CC_id][j] == 0)) + || ((j < (N_RBG[CC_id] - 1)) + && + (ue_sched_ctl-> + rballoc_sub_UE[CC_id][j + + 1] + == 0))) + && + (nb_rbs_required_remaining + [CC_id] + [UE_id2] > 0)) { + + if ((((eNB_UE_stats2-> + DL_pmi_single ^ + eNB_UE_stats1-> + DL_pmi_single) + << (14 - j)) & 0xc000) == 0x4000) { //MU-MIMO only for 25 RBs configuration + + rballoc_sub[CC_id][j] = 1; + ue_sched_ctl-> + rballoc_sub_UE[CC_id] + [j] = 1; + ue_sched_ctl2-> + rballoc_sub_UE[CC_id] + [j] = 1; + MIMO_mode_indicator[CC_id] + [j] = 0; + + if (j < N_RBG[CC_id] - 1) { + rballoc_sub[CC_id][j + + 1] = + 1; + ue_sched_ctl-> + rballoc_sub_UE + [CC_id][j + 1] = 1; + ue_sched_ctl2->rballoc_sub_UE + [CC_id][j + 1] = 1; + MIMO_mode_indicator + [CC_id][j + 1] + = 0; + } + + ue_sched_ctl-> + dl_pow_off[CC_id] + = 0; + ue_sched_ctl2-> + dl_pow_off[CC_id] + = 0; + + + if ((j == N_RBG[CC_id] - 1) + && ((N_RB_DL == 25) + || (N_RB_DL == + 50))) { + + nb_rbs_required_remaining + [CC_id][UE_id] = + nb_rbs_required_remaining + [CC_id][UE_id] - + min_rb_unit[CC_id] + + 1; + ue_sched_ctl->pre_nb_available_rbs + [CC_id] = + ue_sched_ctl->pre_nb_available_rbs + [CC_id] + + min_rb_unit[CC_id] + - 1; + nb_rbs_required_remaining + [CC_id][UE_id2] = + nb_rbs_required_remaining + [CC_id][UE_id2] - + min_rb_unit[CC_id] + + 1; + ue_sched_ctl2->pre_nb_available_rbs + [CC_id] = + ue_sched_ctl2->pre_nb_available_rbs + [CC_id] + + min_rb_unit[CC_id] + - 1; + } else { + + nb_rbs_required_remaining + [CC_id][UE_id] = + nb_rbs_required_remaining + [CC_id][UE_id] - 4; + ue_sched_ctl->pre_nb_available_rbs + [CC_id] = + ue_sched_ctl->pre_nb_available_rbs + [CC_id] + 4; + nb_rbs_required_remaining + [CC_id][UE_id2] = + nb_rbs_required_remaining + [CC_id][UE_id2] - + 4; + ue_sched_ctl2->pre_nb_available_rbs + [CC_id] = + ue_sched_ctl2->pre_nb_available_rbs + [CC_id] + 4; + } + + break; + } + } + } + } + } + } + } +#endif + } + } + } // total_ue_count + } // end of for for r1 and r2 - // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti ); - if(rnti == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) - continue; +#ifdef TM5 - transmission_mode = get_tmode(Mod_id,CC_id,UE_id); - // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0); - //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti); - /* 1st allocate for the retx */ - - // retransmission in data channels - // control channel in the 1st transmission - // data channel for all TM - LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate (Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - transmission_mode, - min_rb_unit[CC_id], - to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth), - nb_rbs_required, - nb_rbs_required_remaining, - rballoc_sub, - MIMO_mode_indicator); + // This has to be revisited!!!! + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + i1 = 0; + i2 = 0; + i3 = 0; + + for (j = 0; j < N_RBG[CC_id]; j++) { + if (MIMO_mode_indicator[CC_id][j] == 2) { + i1 = i1 + 1; + } else if (MIMO_mode_indicator[CC_id][j] == 1) { + i2 = i2 + 1; + } else if (MIMO_mode_indicator[CC_id][j] == 0) { + i3 = i3 + 1; + } + } -#ifdef TM5 + if ((i1 < N_RBG[CC_id]) && (i2 > 0) && (i3 == 0)) { + PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = + PHY_vars_eNB_g[Mod_id][CC_id]-> + check_for_SUMIMO_transmissions + 1; + } - // data chanel TM5: to be revisted - if ((round == 0 ) && - (transmission_mode == 5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - - for(j=0; j<N_RBG[CC_id]; j+=2) { - - if( (((j == (N_RBG[CC_id]-1))&& (rballoc_sub[CC_id][j] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0)) || - ((j < (N_RBG[CC_id]-1)) && (rballoc_sub[CC_id][j+1] == 0) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0)) ) && - (nb_rbs_required_remaining[CC_id][UE_id]>0)) { - - for (ii = UE_list->next[i+1]; ii >=0; ii=UE_list->next[ii]) { - - UE_id2 = ii; - rnti2 = UE_RNTI(Mod_id,UE_id2); - ue_sched_ctl2 = &UE_list->UE_sched_ctrl[UE_id2]; - round2 = ue_sched_ctl2->round[CC_id]; - if(rnti2 == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) - continue; - - eNB_UE_stats2 = UE_list->eNB_UE_stats[CC_id][UE_id2]; - //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); - - if ((mac_eNB_get_rrc_status(Mod_id,rnti2) >= RRC_RECONFIGURED) && - (round2==0) && - (get_tmode(Mod_id,CC_id,UE_id2)==5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - - if( (((j == (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 0)) || - ((j < (N_RBG[CC_id]-1)) && (ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] == 0)) ) && - (nb_rbs_required_remaining[CC_id][UE_id2]>0)) { - - if((((eNB_UE_stats2->DL_pmi_single^eNB_UE_stats1->DL_pmi_single)<<(14-j))&0xc000)== 0x4000) { //MU-MIMO only for 25 RBs configuration - - rballoc_sub[CC_id][j] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][j] = 1; - ue_sched_ctl2->rballoc_sub_UE[CC_id][j] = 1; - MIMO_mode_indicator[CC_id][j] = 0; - - if (j< N_RBG[CC_id]-1) { - rballoc_sub[CC_id][j+1] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][j+1] = 1; - ue_sched_ctl2->rballoc_sub_UE[CC_id][j+1] = 1; - MIMO_mode_indicator[CC_id][j+1] = 0; - } - - ue_sched_ctl->dl_pow_off[CC_id] = 0; - ue_sched_ctl2->dl_pow_off[CC_id] = 0; - - - if ((j == N_RBG[CC_id]-1) && - ((N_RB_DL == 25) || - (N_RB_DL == 50))) { - - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit[CC_id]+1; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1; - nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - min_rb_unit[CC_id]+1; - ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1; - } else { - - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - 4; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + 4; - nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - 4; - ue_sched_ctl2->pre_nb_available_rbs[CC_id] = ue_sched_ctl2->pre_nb_available_rbs[CC_id] + 4; - } - - break; - } - } - } - } - } - } - } + if (i3 == N_RBG[CC_id] && i1 == 0 && i2 == 0) { + PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = + PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + + 1; + } -#endif - } - } - } // total_ue_count - } // end of for for r1 and r2 + if ((i1 < N_RBG[CC_id]) && (i3 > 0)) { + PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = + PHY_vars_eNB_g[Mod_id][CC_id]-> + check_for_MUMIMO_transmissions + 1; + } -#ifdef TM5 + PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = + PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + + 1; - // This has to be revisited!!!! - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - i1=0; - i2=0; - i3=0; - - for (j=0; j<N_RBG[CC_id]; j++) { - if(MIMO_mode_indicator[CC_id][j] == 2) { - i1 = i1+1; - } else if(MIMO_mode_indicator[CC_id][j] == 1) { - i2 = i2+1; - } else if(MIMO_mode_indicator[CC_id][j] == 0) { - i3 = i3+1; - } } - if((i1 < N_RBG[CC_id]) && (i2>0) && (i3==0)) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1; - } +#endif - if(i3 == N_RBG[CC_id] && i1==0 && i2==0) { - PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1; + for (i = UE_list->head; i >= 0; i = UE_list->next[i]) { + UE_id = i; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + + for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) { + CC_id = UE_list->ordered_CCids[ii][UE_id]; + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; + + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { + LOG_D(MAC, + "******************DL Scheduling Information for UE%d ************************\n", + UE_id); + LOG_D(MAC, "dl power offset UE%d = %d \n", UE_id, + ue_sched_ctl->dl_pow_off[CC_id]); + LOG_D(MAC, + "***********RB Alloc for every subband for UE%d ***********\n", + UE_id); + + for (j = 0; j < N_RBG[CC_id]; j++) { + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i]; + LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n", + UE_id, j, + ue_sched_ctl->rballoc_sub_UE[CC_id][j]); + } + + //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; + LOG_D(MAC, "Total RBs allocated for UE%d = %d\n", UE_id, + ue_sched_ctl->pre_nb_available_rbs[CC_id]); + } + } } +} - if((i1 < N_RBG[CC_id]) && (i3 > 0)) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1; - } +#define SF0_LIMIT 1 - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1; +void +dlsch_scheduler_pre_processor_reset(int module_idP, + int UE_id, + uint8_t CC_id, + int frameP, + int subframeP, + int N_RBG, + uint16_t nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs][NUMBER_OF_UE_MAX], + unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], unsigned char + MIMO_mode_indicator[MAX_NUM_CCs] + [N_RBG_MAX]) +{ + int i, j; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + rnti_t rnti = UE_RNTI(module_idP, UE_id); + + uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; + int N_RB_DL = + to_prb(RC.mac[module_idP]->common_channels[CC_id].mib-> + message.dl_Bandwidth); + int RBGsize = N_RB_DL / N_RBG, RBGsize_last; +#ifdef SF0_LIMIT + int sf0_upper = -1, sf0_lower = -1; +#endif - } -#endif + LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); + // initialize harq_pid and round - for(i=UE_list->head; i>=0; i=UE_list->next[i]) { - UE_id = i; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (ue_sched_ctl->ta_timer) + ue_sched_ctl->ta_timer--; - for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { - CC_id = UE_list->ordered_CCids[ii][UE_id]; - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; + /* + eNB_UE_stats *eNB_UE_stats; - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) { - LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id); - LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]); - LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id); + if (eNB_UE_stats == NULL) + return; - for(j=0; j<N_RBG[CC_id]; j++) { - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i]; - LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]); - } - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; - LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]); - } - } - } -} + mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, + frameP,subframeP, + &ue_sched_ctl->harq_pid[CC_id], + &ue_sched_ctl->round[CC_id], + openair_harq_DL); -#define SF0_LIMIT 1 -void dlsch_scheduler_pre_processor_reset (int module_idP, - int UE_id, - uint8_t CC_id, - int frameP, - int subframeP, - int N_RBG, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) - -{ - int i,j; - UE_list_t *UE_list=&RC.mac[module_idP]->UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - rnti_t rnti = UE_RNTI(module_idP,UE_id); - - uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; - int N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); - int RBGsize = N_RB_DL/N_RBG,RBGsize_last; -#ifdef SF0_LIMIT - int sf0_upper=-1,sf0_lower=-1; -#endif + if (ue_sched_ctl->ta_timer == 0) { + // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... - LOG_D(MAC,"Running preprocessor for UE %d (%x)\n",UE_id,rnti); - // initialize harq_pid and round + ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY + switch (N_RB_DL) { + case 6: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; + break; - if (ue_sched_ctl->ta_timer) ue_sched_ctl->ta_timer--; + case 15: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; + break; - /* - eNB_UE_stats *eNB_UE_stats; + case 25: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; + break; - if (eNB_UE_stats == NULL) - return; + case 50: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; + break; - - mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, - frameP,subframeP, - &ue_sched_ctl->harq_pid[CC_id], - &ue_sched_ctl->round[CC_id], - openair_harq_DL); - + case 75: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; + break; - if (ue_sched_ctl->ta_timer == 0) { + case 100: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; + break; + } + // clear the update in case PHY does not have a new measurement after timer expiry + eNB_UE_stats->timing_advance_update = 0; + } + else { + ue_sched_ctl->ta_timer--; + ue_sched_ctl->ta_update =0; // don't trigger a timing advance command + } + + + if (UE_id==0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); + } + */ - // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... + nb_rbs_required[CC_id][UE_id] = 0; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctl->dl_pow_off[CC_id] = 2; + nb_rbs_required_remaining[CC_id][UE_id] = 0; - ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY switch (N_RB_DL) { case 6: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; - break; - + RBGsize = 1; + RBGsize_last = 1; + break; case 15: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; - break; - + RBGsize = 2; + RBGsize_last = 1; + break; case 25: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; - break; - + RBGsize = 2; + RBGsize_last = 1; + break; case 50: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; - break; - + RBGsize = 3; + RBGsize_last = 2; + break; case 75: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; - break; - + RBGsize = 4; + RBGsize_last = 3; + break; case 100: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; - break; + RBGsize = 4; + RBGsize_last = 4; + break; + default: + AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); } - // clear the update in case PHY does not have a new measurement after timer expiry - eNB_UE_stats->timing_advance_update = 0; - } - else { - ue_sched_ctl->ta_timer--; - ue_sched_ctl->ta_update =0; // don't trigger a timing advance command - } - - if (UE_id==0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); - } - */ - - nb_rbs_required[CC_id][UE_id]=0; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; - ue_sched_ctl->dl_pow_off[CC_id] = 2; - nb_rbs_required_remaining[CC_id][UE_id] = 0; - - switch (N_RB_DL) { - case 6: RBGsize = 1; RBGsize_last = 1; break; - case 15: RBGsize = 2; RBGsize_last = 1; break; - case 25: RBGsize = 2; RBGsize_last = 1; break; - case 50: RBGsize = 3; RBGsize_last = 2; break; - case 75: RBGsize = 4; RBGsize_last = 3; break; - case 100: RBGsize = 4; RBGsize_last = 4; break; - default: AssertFatal(1==0,"unsupported RBs (%d)\n", N_RB_DL); - } - #ifdef SF0_LIMIT - switch (N_RBG) { - case 6: - sf0_lower=0; - sf0_upper=5; - break; - case 8: - sf0_lower=2; - sf0_upper=5; - break; - case 13: - sf0_lower=4; - sf0_upper=7; - break; - case 17: - sf0_lower=7; - sf0_upper=9; - break; - case 25: - sf0_lower=11; - sf0_upper=13; - break; - default: AssertFatal(1==0,"unsupported RBs (%d)\n", N_RB_DL); - } + switch (N_RBG) { + case 6: + sf0_lower = 0; + sf0_upper = 5; + break; + case 8: + sf0_lower = 2; + sf0_upper = 5; + break; + case 13: + sf0_lower = 4; + sf0_upper = 7; + break; + case 17: + sf0_lower = 7; + sf0_upper = 9; + break; + case 25: + sf0_lower = 11; + sf0_upper = 13; + break; + default: + AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); + } #endif - // Initialize Subbands according to VRB map - for (i=0; i<N_RBG; i++) { - int rb_size = i==N_RBG-1 ? RBGsize_last : RBGsize; + // Initialize Subbands according to VRB map + for (i = 0; i < N_RBG; i++) { + int rb_size = i == N_RBG - 1 ? RBGsize_last : RBGsize; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; - rballoc_sub[CC_id][i] = 0; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; + rballoc_sub[CC_id][i] = 0; #ifdef SF0_LIMIT - // for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors) - /* TODO: make it proper - allocate those RBs, do not "protect" them, but - * compute number of available REs and limit MCS according to the - * TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor) - */ - if (subframeP==0 && - i >= sf0_lower && i <= sf0_upper) - rballoc_sub[CC_id][i]=1; + // for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors) + /* TODO: make it proper - allocate those RBs, do not "protect" them, but + * compute number of available REs and limit MCS according to the + * TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor) + */ + if (subframeP == 0 && i >= sf0_lower && i <= sf0_upper) + rballoc_sub[CC_id][i] = 1; #endif - // for SI-RNTI,RA-RNTI and P-RNTI allocations - for (j = 0; j < rb_size; j++) { - if (vrb_map[j+(i*RBGsize)] != 0) { - rballoc_sub[CC_id][i] = 1; - LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize)); - break; - } + // for SI-RNTI,RA-RNTI and P-RNTI allocations + for (j = 0; j < rb_size; j++) { + if (vrb_map[j + (i * RBGsize)] != 0) { + rballoc_sub[CC_id][i] = 1; + LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", + frameP, subframeP, j + (i * RBGsize)); + break; + } + } + LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", + frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); + MIMO_mode_indicator[CC_id][i] = 2; } - LOG_D(MAC,"Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",frameP,subframeP,CC_id,i,rballoc_sub[CC_id][i]); - MIMO_mode_indicator[CC_id][i] = 2; - } } -void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int transmission_mode, - int min_rb_unit, - uint8_t N_RB_DL, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) +void +dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + int transmission_mode, + int min_rb_unit, + uint8_t N_RB_DL, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], unsigned char + MIMO_mode_indicator + [MAX_NUM_CCs][N_RBG_MAX]) { - int i; - UE_list_t *UE_list=&RC.mac[Mod_id]->UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for(i=0; i<N_RBG; i++) { - - if((rballoc_sub[CC_id][i] == 0) && - (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) && - (nb_rbs_required_remaining[CC_id][UE_id]>0) && - (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) { - - // if this UE is not scheduled for TM5 - if (ue_sched_ctl->dl_pow_off[CC_id] != 0 ) { - - if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit-1){ - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - if (transmission_mode == 5 ) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; - } - } else { - if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit){ - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - if (transmission_mode == 5 ) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; - } + int i; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + + for (i = 0; i < N_RBG; i++) { + + if ((rballoc_sub[CC_id][i] == 0) && + (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) && + (nb_rbs_required_remaining[CC_id][UE_id] > 0) && + (ue_sched_ctl->pre_nb_available_rbs[CC_id] < + nb_rbs_required[CC_id][UE_id])) { + + // if this UE is not scheduled for TM5 + if (ue_sched_ctl->dl_pow_off[CC_id] != 0) { + + if ((i == N_RBG - 1) + && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + if (nb_rbs_required_remaining[CC_id][UE_id] >= + min_rb_unit - 1) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + MIMO_mode_indicator[CC_id][i] = 1; + if (transmission_mode == 5) { + ue_sched_ctl->dl_pow_off[CC_id] = 1; + } + nb_rbs_required_remaining[CC_id][UE_id] = + nb_rbs_required_remaining[CC_id][UE_id] - + min_rb_unit + 1; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + + min_rb_unit - 1; + } + } else { + if (nb_rbs_required_remaining[CC_id][UE_id] >= + min_rb_unit) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + MIMO_mode_indicator[CC_id][i] = 1; + if (transmission_mode == 5) { + ue_sched_ctl->dl_pow_off[CC_id] = 1; + } + nb_rbs_required_remaining[CC_id][UE_id] = + nb_rbs_required_remaining[CC_id][UE_id] - + min_rb_unit; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + + min_rb_unit; + } + } + } // dl_pow_off[CC_id][UE_id] ! = 0 } - } // dl_pow_off[CC_id][UE_id] ! = 0 } - } } /// ULSCH PRE_PROCESSOR -void ulsch_scheduler_pre_processor(module_id_t module_idP, - int frameP, - sub_frame_t subframeP, - uint16_t *first_rb) +void +ulsch_scheduler_pre_processor(module_id_t module_idP, + int frameP, + sub_frame_t subframeP, uint16_t * first_rb) { - int16_t i; - uint16_t UE_id,n,r; - uint8_t CC_id, harq_pid; - uint16_t nb_allocated_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX],total_allocated_rbs[MAX_NUM_CCs],average_rbs_per_user[MAX_NUM_CCs]; - int16_t total_remaining_rbs[MAX_NUM_CCs]; - uint16_t max_num_ue_to_be_scheduled = 0; - uint16_t total_ue_count = 0; - rnti_t rnti = -1; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - UE_TEMPLATE *UE_template = 0; - int N_RB_DL; - int N_RB_UL; - LOG_D(MAC,"In ulsch_preprocessor: assign max mcs min rb\n"); - // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB - assign_max_mcs_min_rb(module_idP,frameP, subframeP, first_rb); - - LOG_D(MAC,"In ulsch_preprocessor: sort ue \n"); - // sort ues - sort_ue_ul (module_idP,frameP, subframeP); - - - // we need to distribute RBs among UEs - // step1: reset the vars - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); - N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); - total_allocated_rbs[CC_id] = 0; - total_remaining_rbs[CC_id] = 0; - average_rbs_per_user[CC_id] = 0; - - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - nb_allocated_rbs[CC_id][i]=0; + int16_t i; + uint16_t UE_id, n, r; + uint8_t CC_id, harq_pid; + uint16_t nb_allocated_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + total_allocated_rbs[MAX_NUM_CCs], + average_rbs_per_user[MAX_NUM_CCs]; + int16_t total_remaining_rbs[MAX_NUM_CCs]; + uint16_t max_num_ue_to_be_scheduled = 0; + uint16_t total_ue_count = 0; + rnti_t rnti = -1; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_TEMPLATE *UE_template = 0; + int N_RB_DL; + int N_RB_UL; + LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); + // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB + assign_max_mcs_min_rb(module_idP, frameP, subframeP, first_rb); + + LOG_D(MAC, "In ulsch_preprocessor: sort ue \n"); + // sort ues + sort_ue_ul(module_idP, frameP, subframeP); + + + // we need to distribute RBs among UEs + // step1: reset the vars + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + N_RB_DL = + to_prb(RC.mac[module_idP]->common_channels[CC_id].mib-> + message.dl_Bandwidth); + N_RB_UL = + to_prb(RC.mac[module_idP]->common_channels[CC_id]. + ul_Bandwidth); + total_allocated_rbs[CC_id] = 0; + total_remaining_rbs[CC_id] = 0; + average_rbs_per_user[CC_id] = 0; + + for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { + nb_allocated_rbs[CC_id][i] = 0; + } } - } - LOG_D(MAC,"In ulsch_preprocessor: step2 \n"); - // step 2: calculate the average rb per UE - total_ue_count =0; - max_num_ue_to_be_scheduled=0; - - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - - rnti = UE_RNTI(module_idP,i); - - if (rnti==NOT_A_RNTI) - continue; - - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - - UE_id = i; - - LOG_D(MAC,"In ulsch_preprocessor: handling UE %d/%x\n",UE_id,rnti); - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - LOG_D(MAC,"In ulsch_preprocessor: handling UE %d/%x CCid %d\n",UE_id,rnti,CC_id); - UE_template = &UE_list->UE_template[CC_id][UE_id]; - average_rbs_per_user[CC_id]=0; - - if (UE_template->pre_allocated_nb_rb_ul > 0) { - total_ue_count+=1; - } - /* - if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<<aggregation)) { - nCCE_to_be_used[CC_id] = nCCE_to_be_used[CC_id] + (1<<aggregation); - max_num_ue_to_be_scheduled+=1; - }*/ - - max_num_ue_to_be_scheduled+=1; - - if (total_ue_count == 0) { - average_rbs_per_user[CC_id] = 0; - } else if (total_ue_count == 1 ) { // increase the available RBs, special case, - average_rbs_per_user[CC_id] = N_RB_UL-first_rb[CC_id]+1; - } else if( (total_ue_count <= (N_RB_DL-first_rb[CC_id])) && - (total_ue_count <= max_num_ue_to_be_scheduled)) { - average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/total_ue_count); - } else if (max_num_ue_to_be_scheduled > 0 ) { - average_rbs_per_user[CC_id] = (uint16_t) floor((N_RB_UL-first_rb[CC_id])/max_num_ue_to_be_scheduled); - } else { - average_rbs_per_user[CC_id]=1; - LOG_W(MAC,"[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n", - module_idP,frameP,subframeP,UE_id,CC_id); - } + LOG_D(MAC, "In ulsch_preprocessor: step2 \n"); + // step 2: calculate the average rb per UE + total_ue_count = 0; + max_num_ue_to_be_scheduled = 0; + + for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { + + rnti = UE_RNTI(module_idP, i); + + if (rnti == NOT_A_RNTI) + continue; + + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + + + UE_id = i; + + LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", UE_id, + rnti); + for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + // This is the actual CC_id in the list + CC_id = UE_list->ordered_ULCCids[n][UE_id]; + LOG_D(MAC, + "In ulsch_preprocessor: handling UE %d/%x CCid %d\n", + UE_id, rnti, CC_id); + UE_template = &UE_list->UE_template[CC_id][UE_id]; + average_rbs_per_user[CC_id] = 0; + + if (UE_template->pre_allocated_nb_rb_ul > 0) { + total_ue_count += 1; + } + /* + if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<<aggregation)) { + nCCE_to_be_used[CC_id] = nCCE_to_be_used[CC_id] + (1<<aggregation); + max_num_ue_to_be_scheduled+=1; + } */ + + max_num_ue_to_be_scheduled += 1; + + if (total_ue_count == 0) { + average_rbs_per_user[CC_id] = 0; + } else if (total_ue_count == 1) { // increase the available RBs, special case, + average_rbs_per_user[CC_id] = + N_RB_UL - first_rb[CC_id] + 1; + } else if ((total_ue_count <= (N_RB_DL - first_rb[CC_id])) + && (total_ue_count <= max_num_ue_to_be_scheduled)) { + average_rbs_per_user[CC_id] = + (uint16_t) floor((N_RB_UL - first_rb[CC_id]) / + total_ue_count); + } else if (max_num_ue_to_be_scheduled > 0) { + average_rbs_per_user[CC_id] = + (uint16_t) floor((N_RB_UL - first_rb[CC_id]) / + max_num_ue_to_be_scheduled); + } else { + average_rbs_per_user[CC_id] = 1; + LOG_W(MAC, + "[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n", + module_idP, frameP, subframeP, UE_id, CC_id); + } + } } - } - if (total_ue_count > 0) - LOG_D(MAC,"[eNB %d] Frame %d subframe %d: total ue to be scheduled %d/%d\n", - module_idP, frameP, subframeP,total_ue_count, max_num_ue_to_be_scheduled); + if (total_ue_count > 0) + LOG_D(MAC, + "[eNB %d] Frame %d subframe %d: total ue to be scheduled %d/%d\n", + module_idP, frameP, subframeP, total_ue_count, + max_num_ue_to_be_scheduled); - //LOG_D(MAC,"step3\n"); + //LOG_D(MAC,"step3\n"); - // step 3: assigne RBS - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - rnti = UE_RNTI(module_idP,i); + // step 3: assigne RBS + for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { + rnti = UE_RNTI(module_idP, i); - if (rnti==NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; - UE_id = i; + UE_id = i; - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id],frameP,subframeP); + for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + // This is the actual CC_id in the list + CC_id = UE_list->ordered_ULCCids[n][UE_id]; + harq_pid = + subframe2harqpid(&RC.mac[module_idP]-> + common_channels[CC_id], frameP, + subframeP); - // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); + // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); - if(UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id]>0) { - nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; - } else { - nb_allocated_rbs[CC_id][UE_id] = cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user[CC_id]); - } + if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id] > 0) { + nb_allocated_rbs[CC_id][UE_id] = + UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + } else { + nb_allocated_rbs[CC_id][UE_id] = + cmin(UE_list-> + UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, + average_rbs_per_user[CC_id]); + } - total_allocated_rbs[CC_id]+= nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC,"In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n",nb_allocated_rbs[CC_id][UE_id],UE_id,rnti,CC_id,harq_pid); + total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; + LOG_D(MAC, + "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", + nb_allocated_rbs[CC_id][UE_id], UE_id, rnti, CC_id, + harq_pid); + } } - } - // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly - for(r=0; r<2; r++) { - - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - rnti = UE_RNTI(module_idP,i); - - if (rnti==NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - UE_id = i; - - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; - total_remaining_rbs[CC_id]=N_RB_UL - first_rb[CC_id] - total_allocated_rbs[CC_id]; - - if (total_ue_count == 1 ) { - total_remaining_rbs[CC_id]+=1; - } - - if ( r == 0 ) { - while ( (UE_template->pre_allocated_nb_rb_ul > 0 ) && - (nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul) && - (total_remaining_rbs[CC_id] > 0)) { - nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id]+1,UE_template->pre_allocated_nb_rb_ul); - total_remaining_rbs[CC_id]--; - total_allocated_rbs[CC_id]++; - } - } else { - UE_template->pre_allocated_nb_rb_ul= nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC,"******************UL Scheduling Information for UE%d CC_id %d ************************\n",UE_id, CC_id); - LOG_D(MAC,"[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", module_idP, UE_id, CC_id, UE_template->pre_allocated_nb_rb_ul); - } - } + // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly + for (r = 0; r < 2; r++) { + + for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { + rnti = UE_RNTI(module_idP, i); + + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + UE_id = i; + + for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + // This is the actual CC_id in the list + CC_id = UE_list->ordered_ULCCids[n][UE_id]; + UE_template = &UE_list->UE_template[CC_id][UE_id]; + total_remaining_rbs[CC_id] = + N_RB_UL - first_rb[CC_id] - total_allocated_rbs[CC_id]; + + if (total_ue_count == 1) { + total_remaining_rbs[CC_id] += 1; + } + + if (r == 0) { + while ((UE_template->pre_allocated_nb_rb_ul > 0) && + (nb_allocated_rbs[CC_id][UE_id] < + UE_template->pre_allocated_nb_rb_ul) + && (total_remaining_rbs[CC_id] > 0)) { + nb_allocated_rbs[CC_id][UE_id] = + cmin(nb_allocated_rbs[CC_id][UE_id] + 1, + UE_template->pre_allocated_nb_rb_ul); + total_remaining_rbs[CC_id]--; + total_allocated_rbs[CC_id]++; + } + } else { + UE_template->pre_allocated_nb_rb_ul = + nb_allocated_rbs[CC_id][UE_id]; + LOG_D(MAC, + "******************UL Scheduling Information for UE%d CC_id %d ************************\n", + UE_id, CC_id); + LOG_D(MAC, + "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", + module_idP, UE_id, CC_id, + UE_template->pre_allocated_nb_rb_ul); + } + } + } } - } - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - if (total_allocated_rbs[CC_id]>0) { - LOG_D(MAC,"[eNB %d] total RB allocated for all UEs = %d/%d\n", module_idP, total_allocated_rbs[CC_id], N_RB_UL - first_rb[CC_id]); + if (total_allocated_rbs[CC_id] > 0) { + LOG_D(MAC, "[eNB %d] total RB allocated for all UEs = %d/%d\n", + module_idP, total_allocated_rbs[CC_id], + N_RB_UL - first_rb[CC_id]); + } } - } } -void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP, uint16_t *first_rb) +void +assign_max_mcs_min_rb(module_id_t module_idP, int frameP, + sub_frame_t subframeP, uint16_t * first_rb) { - int i; - uint16_t n,UE_id; - uint8_t CC_id; - rnti_t rnti = -1; - int mcs; - int rb_table_index=0,tbs,tx_power; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - - UE_TEMPLATE *UE_template; - int Ncp; - int N_RB_UL; - - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) continue; - - rnti = UE_RNTI(module_idP,i); - - if (rnti==NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - if (UE_list->UE_sched_ctrl[i].phr_received == 1) - mcs = 20; // if we've received the power headroom information the UE, we can go to maximum mcs - else - mcs = 10; // otherwise, limit to QPSK PUSCH - - UE_id = i; - - for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - - if (CC_id >= MAX_NUM_CCs) { - LOG_E( MAC, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", - CC_id, - MAX_NUM_CCs, - n, - UE_id, - UE_list->numactiveULCCs[UE_id]); - } - - AssertFatal( CC_id < MAX_NUM_CCs, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", - CC_id, - MAX_NUM_CCs, - n, - UE_id, - UE_list->numactiveULCCs[UE_id]); - - UE_template = &UE_list->UE_template[CC_id][UE_id]; - - Ncp = RC.mac[module_idP]->common_channels[CC_id].Ncp; - N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); - // if this UE has UL traffic - if (UE_template->ul_total_buffer > 0 ) { - - - tbs = get_TBS_UL(mcs,3)<<3; // 1 or 2 PRB with cqi enabled does not work well! - rb_table_index = 2; - - // fixme: set use_srs flag - tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0); - - while ((((UE_template->phr_info - tx_power) < 0 ) || (tbs > UE_template->ul_total_buffer))&& - (mcs > 3)) { - // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); - mcs--; - tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3; - tx_power = estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0); // fixme: set use_srs - } - - while ((tbs < UE_template->ul_total_buffer) && - (rb_table[rb_table_index]<(N_RB_UL-first_rb[CC_id])) && - ((UE_template->phr_info - tx_power) > 0) && - (rb_table_index < 32 )) { - - rb_table_index++; - tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3; - tx_power = estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,Ncp,0); - } - - UE_template->ue_tx_power = tx_power; - - if (rb_table[rb_table_index]>(N_RB_UL-first_rb[CC_id]-1)) { - rb_table_index--; - } - - // 1 or 2 PRB with cqi enabled does not work well - if (rb_table[rb_table_index]<3) { - rb_table_index=2; //3PRB - } - - UE_template->pre_assigned_mcs_ul=mcs; - UE_template->pre_allocated_rb_table_index_ul=rb_table_index; - UE_template->pre_allocated_nb_rb_ul= rb_table[rb_table_index]; - LOG_D(MAC,"[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", - module_idP, frameP, subframeP, UE_id, CC_id, - UE_template->pre_assigned_mcs_ul, - UE_template->pre_allocated_rb_table_index_ul, - UE_template->pre_allocated_nb_rb_ul, - UE_template->phr_info,tx_power); - } else { - /* if UE has pending scheduling request then pre-allocate 3 RBs */ - //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { - if (UE_is_to_be_scheduled(module_idP, CC_id, i)) { - /* use QPSK mcs */ - UE_template->pre_assigned_mcs_ul = 10; - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul = 3; - } else { - UE_template->pre_assigned_mcs_ul = 0; - UE_template->pre_allocated_rb_table_index_ul = -1; - UE_template->pre_allocated_nb_rb_ul = 0; - } - } - } - } -} + int i; + uint16_t n, UE_id; + uint8_t CC_id; + rnti_t rnti = -1; + int mcs; + int rb_table_index = 0, tbs, tx_power; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + UE_list_t *UE_list = &eNB->UE_list; -struct sort_ue_ul_params { - int module_idP; - int frameP; - int subframeP; -}; + UE_TEMPLATE *UE_template; + int Ncp; + int N_RB_UL; -static int ue_ul_compare(const void *_a, const void *_b, void *_params) -{ - struct sort_ue_ul_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) + continue; + + rnti = UE_RNTI(module_idP, i); + + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; - int UE_id1 = *(const int *)_a; - int UE_id2 = *(const int *)_b; + if (UE_list->UE_sched_ctrl[i].phr_received == 1) + mcs = 20; // if we've received the power headroom information the UE, we can go to maximum mcs + else + mcs = 10; // otherwise, limit to QPSK PUSCH - int rnti1 = UE_RNTI(params->module_idP, UE_id1); - int pCCid1 = UE_PCCID(params->module_idP, UE_id1); - int round1 = maxround(params->module_idP, rnti1, params->frameP, params->subframeP, 1); + UE_id = i; - int rnti2 = UE_RNTI(params->module_idP, UE_id2); - int pCCid2 = UE_PCCID(params->module_idP, UE_id2); - int round2 = maxround(params->module_idP, rnti2, params->frameP, params->subframeP, 1); + for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + // This is the actual CC_id in the list + CC_id = UE_list->ordered_ULCCids[n][UE_id]; - if (round1 > round2) return -1; - if (round1 < round2) return 1; + if (CC_id >= MAX_NUM_CCs) { + LOG_E(MAC, + "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", + CC_id, MAX_NUM_CCs, n, UE_id, + UE_list->numactiveULCCs[UE_id]); + } - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return -1; - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return 1; + AssertFatal(CC_id < MAX_NUM_CCs, + "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", + CC_id, MAX_NUM_CCs, n, UE_id, + UE_list->numactiveULCCs[UE_id]); + + UE_template = &UE_list->UE_template[CC_id][UE_id]; + + Ncp = RC.mac[module_idP]->common_channels[CC_id].Ncp; + N_RB_UL = + to_prb(RC.mac[module_idP]->common_channels[CC_id]. + ul_Bandwidth); + // if this UE has UL traffic + if (UE_template->ul_total_buffer > 0) { + + + tbs = get_TBS_UL(mcs, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! + rb_table_index = 2; + + // fixme: set use_srs flag + tx_power = + estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, + Ncp, 0); + + while ((((UE_template->phr_info - tx_power) < 0) + || (tbs > UE_template->ul_total_buffer)) + && (mcs > 3)) { + // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); + mcs--; + tbs = get_TBS_UL(mcs, rb_table[rb_table_index]) << 3; + tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs + } + + while ((tbs < UE_template->ul_total_buffer) && + (rb_table[rb_table_index] < + (N_RB_UL - first_rb[CC_id])) + && ((UE_template->phr_info - tx_power) > 0) + && (rb_table_index < 32)) { + + rb_table_index++; + tbs = get_TBS_UL(mcs, rb_table[rb_table_index]) << 3; + tx_power = + estimate_ue_tx_power(tbs, rb_table[rb_table_index], + 0, Ncp, 0); + } + + UE_template->ue_tx_power = tx_power; + + if (rb_table[rb_table_index] > + (N_RB_UL - first_rb[CC_id] - 1)) { + rb_table_index--; + } + // 1 or 2 PRB with cqi enabled does not work well + if (rb_table[rb_table_index] < 3) { + rb_table_index = 2; //3PRB + } + + UE_template->pre_assigned_mcs_ul = mcs; + UE_template->pre_allocated_rb_table_index_ul = + rb_table_index; + UE_template->pre_allocated_nb_rb_ul = + rb_table[rb_table_index]; + LOG_D(MAC, + "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", + module_idP, frameP, subframeP, UE_id, CC_id, + UE_template->pre_assigned_mcs_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_allocated_nb_rb_ul, + UE_template->phr_info, tx_power); + } else { + /* if UE has pending scheduling request then pre-allocate 3 RBs */ + //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { + if (UE_is_to_be_scheduled(module_idP, CC_id, i)) { + /* use QPSK mcs */ + UE_template->pre_assigned_mcs_ul = 10; + UE_template->pre_allocated_rb_table_index_ul = 2; + UE_template->pre_allocated_nb_rb_ul = 3; + } else { + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_allocated_nb_rb_ul = 0; + } + } + } + } +} - if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer > UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) - return -1; - if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) - return 1; +struct sort_ue_ul_params { + int module_idP; + int frameP; + int subframeP; +}; - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return -1; - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return 1; +static int ue_ul_compare(const void *_a, const void *_b, void *_params) +{ + struct sort_ue_ul_params *params = _params; + UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list; + + int UE_id1 = *(const int *) _a; + int UE_id2 = *(const int *) _b; + + int rnti1 = UE_RNTI(params->module_idP, UE_id1); + int pCCid1 = UE_PCCID(params->module_idP, UE_id1); + int round1 = maxround(params->module_idP, rnti1, params->frameP, + params->subframeP, 1); + + int rnti2 = UE_RNTI(params->module_idP, UE_id2); + int pCCid2 = UE_PCCID(params->module_idP, UE_id2); + int round2 = maxround(params->module_idP, rnti2, params->frameP, + params->subframeP, 1); + + if (round1 > round2) + return -1; + if (round1 < round2) + return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > + UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < + UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer > + UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < + UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) + return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > + UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < + UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + return 1; - return 0; + return 0; #if 0 - /* The above order derives from the following. - * The last case is not handled: "if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 )" - * I don't think it makes a big difference. - */ - if(round2 > round1) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (round2 == round1) { - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) { - if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } - } - } + /* The above order derives from the following. + * The last case is not handled: "if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 )" + * I don't think it makes a big difference. + */ + if (round2 > round1) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (round2 == round1) { + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < + UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < + UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (UE_list->UE_template[pCCid1][UE_id1]. + pre_assigned_mcs_ul < + UE_list->UE_template[pCCid2][UE_id2]. + pre_assigned_mcs_ul) { + if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } + } + } #endif } -void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) +void sort_ue_ul(module_id_t module_idP, int frameP, sub_frame_t subframeP) { - int i; - int list[NUMBER_OF_UE_MAX]; - int list_size = 0; - int rnti; - struct sort_ue_ul_params params = { module_idP, frameP, subframeP }; + int i; + int list[NUMBER_OF_UE_MAX]; + int list_size = 0; + int rnti; + struct sort_ue_ul_params params = { module_idP, frameP, subframeP }; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] == FALSE) continue; - if ((rnti = UE_RNTI(module_idP, i)) == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] == FALSE) + continue; + if ((rnti = UE_RNTI(module_idP, i)) == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; - list[list_size] = i; - list_size++; - } + list[list_size] = i; + list_size++; + } - qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); + qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); - if (list_size) { - for (i = 0; i < list_size-1; i++) - UE_list->next_ul[list[i]] = list[i+1]; - UE_list->next_ul[list[list_size-1]] = -1; - UE_list->head_ul = list[0]; - } else { - UE_list->head_ul = -1; - } + if (list_size) { + for (i = 0; i < list_size - 1; i++) + UE_list->next_ul[list[i]] = list[i + 1]; + UE_list->next_ul[list[list_size - 1]] = -1; + UE_list->head_ul = list[0]; + } else { + UE_list->head_ul = -1; + } #if 0 - int UE_id1,UE_id2; - int pCCid1,pCCid2; - int round1,round2; - int i=0,ii=0; - rnti_t rnti1,rnti2; - - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - - //LOG_I(MAC,"sort ue ul i %d\n",i); - for (ii=UE_list->next_ul[i]; ii>=0; ii=UE_list->next_ul[ii]) { - //LOG_I(MAC,"sort ul ue 2 ii %d\n",ii); - - UE_id1 = i; - rnti1 = UE_RNTI(module_idP,UE_id1); - - if(rnti1 == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) - continue; - - - pCCid1 = UE_PCCID(module_idP,UE_id1); - round1 = maxround(module_idP,rnti1,frameP,subframeP,1); - - UE_id2 = ii; - rnti2 = UE_RNTI(module_idP,UE_id2); - - if(rnti2 == NOT_A_RNTI) - continue; - if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) - continue; - - pCCid2 = UE_PCCID(module_idP,UE_id2); - round2 = maxround(module_idP,rnti2,frameP,subframeP,1); - - if(round2 > round1) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (round2 == round1) { - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } else if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) { - if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) { - swap_UEs(UE_list,UE_id1,UE_id2,1); - } - } - } + int UE_id1, UE_id2; + int pCCid1, pCCid2; + int round1, round2; + int i = 0, ii = 0; + rnti_t rnti1, rnti2; + + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + + for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { + + //LOG_I(MAC,"sort ue ul i %d\n",i); + for (ii = UE_list->next_ul[i]; ii >= 0; ii = UE_list->next_ul[ii]) { + //LOG_I(MAC,"sort ul ue 2 ii %d\n",ii); + + UE_id1 = i; + rnti1 = UE_RNTI(module_idP, UE_id1); + + if (rnti1 == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + + + pCCid1 = UE_PCCID(module_idP, UE_id1); + round1 = maxround(module_idP, rnti1, frameP, subframeP, 1); + + UE_id2 = ii; + rnti2 = UE_RNTI(module_idP, UE_id2); + + if (rnti2 == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) + continue; + + pCCid2 = UE_PCCID(module_idP, UE_id2); + round2 = maxround(module_idP, rnti2, frameP, subframeP, 1); + + if (round2 > round1) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (round2 == round1) { + if (UE_list-> + UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < + UE_list->UE_template[pCCid2][UE_id2]. + ul_buffer_info[LCGID0]) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (UE_list->UE_template[pCCid1][UE_id1]. + ul_total_buffer < + UE_list->UE_template[pCCid2][UE_id2]. + ul_total_buffer) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } else if (UE_list-> + UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul + < + UE_list-> + UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + { + if (UE_list->UE_template[pCCid2][UE_id2]. + ul_total_buffer > 0) { + swap_UEs(UE_list, UE_id1, UE_id2, 1); + } + } + } + } } - } #endif } diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index b316cbfeeb8333e709106d0e44a2dc024760d454..bbd6d6a36d84d365e6a63bc8b2222303a3a9bf02 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -43,12 +43,11 @@ */ -void schedule_mib(module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP); +void schedule_mib(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP); /** \fn void schedule_RA(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); -\brief First stage of Random-Access Scheduling. Loops over the RA_templates and checks if RAR, Msg3 or its retransmission are to be scheduled in the subframe. It returns the total number of PRB used for RA SDUs. For Msg3 it retrieves the L3msg from RRC and fills the appropriate buffers. For the others it just computes the number of PRBs. Each DCI uses 3 PRBs (format 1A) +\brief First stage of Random-Access Scheduling. Loops over the ras and checks if RAR, Msg3 or its retransmission are to be scheduled in the subframe. It returns the total number of PRB used for RA SDUs. For Msg3 it retrieves the L3msg from RRC and fills the appropriate buffers. For the others it just computes the number of PRBs. Each DCI uses 3 PRBs (format 1A) for the message. @param Mod_id Instance ID of eNB @param frame Frame index @@ -56,28 +55,32 @@ for the message. */ -void schedule_RA(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); +void schedule_RA(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe); /** \brief First stage of SI Scheduling. Gets a SI SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs). @param Mod_id Instance ID of eNB @param frame Frame index @param subframe Subframe number on which to act */ -void schedule_SI(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP); +void schedule_SI(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP); /** \brief MBMS scheduling: Checking the position for MBSFN subframes. Create MSI, transfer MCCH from RRC to MAC, transfer MTCHs from RLC to MAC. Multiplexing MSI,MCCH&MTCHs. Return 1 if there are MBSFN data being allocated, otherwise return 0; @param Mod_id Instance ID of eNB @param frame Frame index @param subframe Subframe number on which to act */ -int schedule_MBMS(module_id_t module_idP,uint8_t CC_id, frame_t frameP, sub_frame_t subframe); +int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + sub_frame_t subframe); /** \brief check the mapping between sf allocation and sync area, Currently only supports 1:1 mapping @param Mod_id Instance ID of eNB @param mbsfn_sync_area index of mbsfn sync area @param[out] index of sf pattern */ -int8_t get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t CC_id, uint8_t mbsfn_sync_area); +int8_t get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, + uint8_t mbsfn_sync_area); /** \brief check the mapping between sf allocation and sync area, Currently only supports 1:1 mapping @param Mod_id Instance ID of eNB @@ -85,14 +88,17 @@ int8_t get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t CC_id, uint8_t mb @param eNB_index index of eNB @param[out] index of sf pattern */ -int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index); +int8_t ue_get_mbsfn_sf_alloction(module_id_t module_idP, + uint8_t mbsfn_sync_area, + unsigned char eNB_index); /** \brief top ULSCH Scheduling for TDD (config 1-6). @param Mod_id Instance ID of eNB @param frame Frame index @param subframe Subframe number on which to act */ -void schedule_ulsch(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); +void schedule_ulsch(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe); /** \brief ULSCH Scheduling per RNTI @param Mod_id Instance ID of eNB @@ -100,7 +106,10 @@ void schedule_ulsch(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); @param subframe Subframe number on which to act @param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup) */ -void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb); +void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe, + unsigned char sched_subframe, + uint16_t * first_rb); /** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4. @param Mod_id Instance of eNB @@ -108,7 +117,8 @@ void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t sub @param subframe Index of subframe @param mbsfn_flag Indicates that this subframe is for MCH/MCCH */ -void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); +void fill_DLSCH_dci(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe, int *mbsfn_flag); /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @@ -117,39 +127,43 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i @param mbsfn_flag Indicates that MCH/MCCH is in this subframe */ -void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); +void schedule_ue_spec(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe, int *mbsfn_flag); /** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure. @param Mod_id Module id of UE @returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE */ -int8_t get_Po_NOMINAL_PUSCH(module_id_t module_idP,uint8_t CC_id); +int8_t get_Po_NOMINAL_PUSCH(module_id_t module_idP, uint8_t CC_id); /** \brief Function to compute DELTA_PREAMBLE from 36.321 (for RA power ramping procedure and Msg3 PUSCH power control policy) @param Mod_id Module id of UE @returns DELTA_PREAMBLE */ -int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id); +int8_t get_DELTA_PREAMBLE(module_id_t module_idP, int CC_id); /** \brief Function for compute deltaP_rampup from 36.321 (for RA power ramping procedure and Msg3 PUSCH power control policy) @param Mod_id Module id of UE @param CC_id carrier component id of UE @returns deltaP_rampup */ -int8_t get_deltaP_rampup(module_id_t module_idP,uint8_t CC_id); +int8_t get_deltaP_rampup(module_id_t module_idP, uint8_t CC_id); -uint16_t mac_computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); +uint16_t mac_computeRIV(uint16_t N_RB_DL, uint16_t RBstart, + uint16_t Lcrbs); -void add_msg3(module_id_t module_idP,int CC_id, RA_TEMPLATE *RA_template, frame_t frameP, sub_frame_t subframeP); +void add_msg3(module_id_t module_idP, int CC_id, RA_t * ra, frame_t frameP, + sub_frame_t subframeP); //main.c -int mac_top_init(int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active); +int mac_top_init(int eMBMS_active, char *uecap_xer, + uint8_t cba_group_active, uint8_t HO_active); void mac_top_init_eNB(void); -void mac_init_cell_params(int Mod_idP,int CC_idP); +void mac_init_cell_params(int Mod_idP, int CC_idP); char layer2_init_UE(module_id_t module_idP); @@ -161,19 +175,29 @@ int mac_init_global_param(void); void mac_top_cleanup(void); -void mac_UE_out_of_sync_ind(module_id_t module_idP,frame_t frameP, uint16_t eNB_index); - -void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP); - -void dlsch_scheduler_pre_processor_reset (int module_idP,int UE_id, - uint8_t CC_id, - int frameP, - int subframeP, - int N_RBG, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]); +void mac_UE_out_of_sync_ind(module_id_t module_idP, frame_t frameP, + uint16_t eNB_index); + +void clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP, + frame_t frameP, sub_frame_t subframeP); + +void dlsch_scheduler_pre_processor_reset(int module_idP, int UE_id, + uint8_t CC_id, + int frameP, + int subframeP, + int N_RBG, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs][NUMBER_OF_UE_MAX], + unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], + unsigned char + MIMO_mode_indicator[MAX_NUM_CCs] + [N_RBG_MAX]); // eNB functions /* \brief This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done @@ -184,24 +208,33 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,int UE_id, */ -void dlsch_scheduler_pre_processor (module_id_t module_idP, - frame_t frameP, - sub_frame_t subframe, - int N_RBG[MAX_NUM_CCs], - int *mbsfn_flag); - - -void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int transmission_mode, - int min_rb_unit, - uint8_t N_RB_DL, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]); +void dlsch_scheduler_pre_processor(module_id_t module_idP, + frame_t frameP, + sub_frame_t subframe, + int N_RBG[MAX_NUM_CCs], + int *mbsfn_flag); + + +void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + int transmission_mode, + int min_rb_unit, + uint8_t N_RB_DL, + uint16_t + nb_rbs_required[MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + uint16_t + nb_rbs_required_remaining + [MAX_NUM_CCs] + [NUMBER_OF_UE_MAX], + unsigned char + rballoc_sub[MAX_NUM_CCs] + [N_RBG_MAX], + unsigned char + MIMO_mode_indicator + [MAX_NUM_CCs][N_RBG_MAX]); /* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. @@ -209,7 +242,7 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id, @param subframe Index of current subframe @param calibration_flag Flag to indicate that eNB scheduler should schedule TDD auto-calibration PUSCH. */ -void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);//, int calibration_flag); +void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); //, int calibration_flag); /* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure. @param Mod_id Instance ID of eNB @@ -218,12 +251,13 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame @param rnti RA rnti corresponding to this PRACH preamble @param rach_resource type (0=non BL/CE,1 CE level 0,2 CE level 1, 3 CE level 2,4 CE level 3) */ -void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame_t subframeP, uint16_t preamble_index,int16_t timing_offset,uint16_t rnti +void initiate_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframeP, uint16_t preamble_index, + int16_t timing_offset, uint16_t rnti #ifdef Rel14 - , - uint8_t rach_resource_type + , uint8_t rach_resource_type #endif - ); + ); /* \brief Function in eNB to fill RAR pdu when requested by PHY. This provides a single RAR SDU for the moment and returns the t-CRNTI. @param Mod_id Instance ID of eNB @@ -231,31 +265,30 @@ void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame @param N_RB_UL Number of UL resource blocks @returns t_CRNTI */ -unsigned short fill_rar( - const module_id_t module_idP, - const int CC_id, - const frame_t frameP, - uint8_t * const dlsch_buffer, - const uint16_t N_RB_UL, - const uint8_t input_buffer_length -); +unsigned short fill_rar(const module_id_t module_idP, + const int CC_id, + RA_t *ra, + const frame_t frameP, + uint8_t * const dlsch_buffer, + const uint16_t N_RB_UL, + const uint8_t input_buffer_length); #ifdef Rel14 -unsigned short fill_rar_br(eNB_MAC_INST *eNB, +unsigned short fill_rar_br(eNB_MAC_INST * eNB, int CC_id, - RA_TEMPLATE *RA_template, - const frame_t frameP, - const sub_frame_t subframeP, - uint8_t* const dlsch_buffer, - const uint8_t ce_level - ); + RA_t * ra, + const frame_t frameP, + const sub_frame_t subframeP, + uint8_t * const dlsch_buffer, + const uint8_t ce_level); #endif /* \brief Function to indicate a failed RA response. It removes all temporary variables related to the initial connection of a UE @param Mod_id Instance ID of eNB @param preamble_index index of the received RA request. */ -void cancel_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, uint16_t preamble_index); +void cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, + uint16_t preamble_index); /* \brief Function used by PHY to inform MAC that an uplink is scheduled for Msg3 in given subframe. This is used so that the MAC @@ -269,12 +302,10 @@ void cancel_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, uint16_t pr @param Msg3_subframe subframe where scheduling takes place */ void set_msg3_subframe(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - int rnti, - int Msg3_frame, - int Msg3_subframe); + int CC_id, + int frame, + int subframe, + int rnti, int Msg3_frame, int Msg3_subframe); /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of eNB @@ -286,14 +317,13 @@ void set_msg3_subframe(module_id_t Mod_id, @param ul_cqi Uplink CQI estimate after this pdu (SNR quantized to 8 bits, -64 ... 63.5 dB in .5dB steps) */ void rx_sdu(const module_id_t enb_mod_idP, - const int CC_idP, - const frame_t frameP, + const int CC_idP, + const frame_t frameP, const sub_frame_t subframeP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const uint16_t timing_advance, - const uint8_t ul_cqi); + const rnti_t rntiP, + uint8_t * sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, const uint8_t ul_cqi); /* \brief Function to indicate a scheduled schduling request (SR) was received by eNB. @@ -304,7 +334,8 @@ void rx_sdu(const module_id_t enb_mod_idP, @param rnti RNTI of UE transmitting the SR @param ul_cqi SNR measurement of PUCCH (SNR quantized to 8 bits, -64 ... 63.5 dB in .5dB steps) */ -void SR_indication(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe,rnti_t rnti,uint8_t ul_cqi); +void SR_indication(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, rnti_t rnti, uint8_t ul_cqi); /* \brief Function to indicate a UL failure was detected by eNB PHY. @param Mod_id Instance ID of eNB @@ -313,7 +344,8 @@ void SR_indication(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t s @param rnti RNTI of UE transmitting the SR @param subframe Index of subframe where SR was received */ -void UL_failure_indication(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe); +void UL_failure_indication(module_id_t Mod_id, int CC_id, frame_t frameP, + rnti_t rnti, sub_frame_t subframe); /* \brief Function to indicate an HARQ ACK/NAK. @param Mod_id Instance ID of eNB @@ -322,7 +354,9 @@ void UL_failure_indication(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rn @param subframeP subframe index @param harq_pdu NFAPI HARQ PDU descriptor */ -void harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, nfapi_harq_indication_pdu_t *harq_pdu); +void harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, + nfapi_harq_indication_pdu_t * harq_pdu); /* \brief Function to indicate a received CQI pdu @param Mod_id Instance ID of eNB @@ -332,11 +366,13 @@ void harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_ @param rntiP RNTI of incoming CQI information @param ul_cqi_information NFAPI UL CQI measurement */ -void cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, rnti_t rntiP, - nfapi_cqi_indication_rel9_t *rel9,uint8_t *pdu, - nfapi_ul_cqi_information_t *ul_cqi_information); +void cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, + sub_frame_t subframeP, rnti_t rntiP, + nfapi_cqi_indication_rel9_t * rel9, uint8_t * pdu, + nfapi_ul_cqi_information_t * ul_cqi_information); -uint8_t *get_dlsch_sdu(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TBindex); +uint8_t *get_dlsch_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + rnti_t rnti, uint8_t TBindex); /* \brief Function to retrieve MCH transport block and MCS used for MCH in this MBSFN subframe. Returns null if no MCH is to be transmitted @param Mod_id Instance ID of eNB @@ -345,69 +381,70 @@ uint8_t *get_dlsch_sdu(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rn @param mcs Pointer to mcs used by PHY (to be filled by MAC) @returns Pointer to MCH transport block and mcs for subframe */ -MCH_PDU *get_mch_sdu( module_id_t Mod_id, int CC_id, frame_t frame, sub_frame_t subframe); +MCH_PDU *get_mch_sdu(module_id_t Mod_id, int CC_id, frame_t frame, + sub_frame_t subframe); -void ue_mac_reset (module_id_t module_idP,uint8_t eNB_index); -void ue_init_mac (module_id_t module_idP); -void init_ue_sched_info(void); -void add_ue_ulsch_info (module_id_t module_idP, int CC_id, int UE_id, sub_frame_t subframe,UE_ULSCH_STATUS status); -void add_ue_dlsch_info (module_id_t module_idP, int CC_id,int UE_id, sub_frame_t subframe,UE_DLSCH_STATUS status); -int find_UE_id (module_id_t module_idP, rnti_t rnti) ; -int find_RA_id (module_id_t mod_idP, int CC_idP, rnti_t rntiP); -rnti_t UE_RNTI (module_id_t module_idP, int UE_id); -int UE_PCCID (module_id_t module_idP, int UE_id); -uint8_t find_active_UEs (module_id_t module_idP); -boolean_t is_UE_active (module_id_t module_idP, int UE_id); -uint8_t get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt); +void ue_mac_reset(module_id_t module_idP, uint8_t eNB_index); +void ue_init_mac(module_id_t module_idP); +void init_ue_sched_info(void); +void add_ue_ulsch_info(module_id_t module_idP, int CC_id, int UE_id, + sub_frame_t subframe, UE_ULSCH_STATUS status); +void add_ue_dlsch_info(module_id_t module_idP, int CC_id, int UE_id, + sub_frame_t subframe, UE_DLSCH_STATUS status); +int find_UE_id(module_id_t module_idP, rnti_t rnti); +int find_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP); +rnti_t UE_RNTI(module_id_t module_idP, int UE_id); +int UE_PCCID(module_id_t module_idP, int UE_id); +uint8_t find_active_UEs(module_id_t module_idP); +boolean_t is_UE_active(module_id_t module_idP, int UE_id); +uint8_t get_aggregation(uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt); int8_t find_active_UEs_with_traffic(module_id_t module_idP); -void init_CCE_table(int module_idP,int CC_idP); +void init_CCE_table(int module_idP, int CC_idP); int get_nCCE_offset(int *CCE_table, - const unsigned char L, - const int nCCE, - const int common_dci, - const unsigned short rnti, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, const unsigned char subframe); -int allocate_CCEs(int module_idP, - int CC_idP, - int subframe, - int test_only); +int allocate_CCEs(int module_idP, int CC_idP, int subframe, int test_only); boolean_t CCE_allocation_infeasible(int module_idP, - int CC_idP, - int common_flag, - int subframe, - int aggregation, - int rnti); - -void set_ue_dai(sub_frame_t subframeP, - int UE_id, - uint8_t CC_id, - uint8_t tdd_config, - UE_list_t *UE_list); - -uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, unsigned char group_id); -uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id); + int CC_idP, + int common_flag, + int subframe, + int aggregation, int rnti); + +void set_ue_dai(sub_frame_t subframeP, + int UE_id, + uint8_t CC_id, uint8_t tdd_config, UE_list_t * UE_list); + +uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, + unsigned char group_id); +uint8_t UE_is_to_be_scheduled(module_id_t module_idP, int CC_id, + uint8_t UE_id); /** \brief Round-robin scheduler for ULSCH traffic. @param Mod_id Instance ID for eNB @param subframe Subframe number on which to act @returns UE index that is to be scheduled if needed/room */ -module_id_t schedule_next_ulue(module_id_t module_idP, int UE_id,sub_frame_t subframe); +module_id_t schedule_next_ulue(module_id_t module_idP, int UE_id, + sub_frame_t subframe); /** \brief Round-robin scheduler for DLSCH traffic. @param Mod_id Instance ID for eNB @param subframe Subframe number on which to act @returns UE index that is to be scheduled if needed/room */ -int schedule_next_dlue(module_id_t module_idP, int CC_id, sub_frame_t subframe); +int schedule_next_dlue(module_id_t module_idP, int CC_id, + sub_frame_t subframe); /* \brief Allocates a set of PRBS for a particular UE. This is a simple function for the moment, later it should process frequency-domain CQI information and/or PMI information. Currently it just returns the first PRBS that are available in the subframe based on the number requested. @param UE_id Index of UE on which to act @@ -416,7 +453,8 @@ int schedule_next_dlue(module_id_t module_idP, int CC_id, sub_frame_t subframe); @param rballoc Pointer to bit-map of current PRB allocation given to previous users/control channels. This is updated for subsequent calls to the routine. @returns an rballoc bitmap for resource type 0 allocation (DCI). */ -uint32_t allocate_prbs(int UE_id,uint8_t nb_rb, int N_RB_DL, uint32_t *rballoc); +uint32_t allocate_prbs(int UE_id, uint8_t nb_rb, int N_RB_DL, + uint32_t * rballoc); /* \fn uint32_t req_new_ulsch(module_id_t module_idP) \brief check for a new transmission in any drb @@ -433,19 +471,25 @@ uint32_t req_new_ulsch(module_id_t module_idP); @param subframe subframe number @returns 0 for no SR, 1 for SR */ -uint32_t ue_get_SR(module_id_t module_idP, int CC_id,frame_t frameP, uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe); +uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, + uint8_t eNB_id, rnti_t rnti, sub_frame_t subframe); uint8_t get_ue_weight(module_id_t module_idP, int CC_id, int UE_id); // UE functions -void mac_out_of_sync_ind(module_id_t module_idP, frame_t frameP, uint16_t CH_index); +void mac_out_of_sync_ind(module_id_t module_idP, frame_t frameP, + uint16_t CH_index); -void ue_decode_si(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); +void ue_decode_si(module_id_t module_idP, int CC_id, frame_t frame, + uint8_t CH_index, void *pdu, uint16_t len); -void ue_decode_p(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); +void ue_decode_p(module_id_t module_idP, int CC_id, frame_t frame, + uint8_t CH_index, void *pdu, uint16_t len); -void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, sub_frame_t subframe, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); +void ue_send_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frame, + sub_frame_t subframe, uint8_t * sdu, uint16_t sdu_len, + uint8_t CH_index); #if defined(Rel10) || defined(Rel14) @@ -457,7 +501,9 @@ void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, sub_frame_ @param eNB_index Index of attached eNB @param sync_area the index of MBSFN sync area */ -void ue_send_mch_sdu(module_id_t module_idP,uint8_t CC_id, frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index,uint8_t sync_area) ; +void ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + uint8_t * sdu, uint16_t sdu_len, uint8_t eNB_index, + uint8_t sync_area); /*\brief Function to check if UE PHY needs to decode MCH for MAC. @param Mod_id Index of protocol instance @@ -467,7 +513,9 @@ void ue_send_mch_sdu(module_id_t module_idP,uint8_t CC_id, frame_t frameP,uint8_ @param[out] sync_area return the sync area @param[out] mcch_active flag indicating whether this MCCH is active in this SF */ -int ue_query_mch(uint8_t Mod_id,uint8_t CC_id, uint32_t frame,sub_frame_t subframe, uint8_t eNB_index, uint8_t *sync_area, uint8_t *mcch_active); +int ue_query_mch(uint8_t Mod_id, uint8_t CC_id, uint32_t frame, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * sync_area, uint8_t * mcch_active); #endif @@ -478,7 +526,10 @@ int ue_query_mch(uint8_t Mod_id,uint8_t CC_id, uint32_t frame,sub_frame_t subfra @param subframe subframe number @returns 0 for no SR, 1 for SR */ -void ue_get_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen,uint8_t *access_mode); +void ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * ulsch_buffer, uint16_t buflen, + uint8_t * access_mode); /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for random-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 36.321) @param Mod_id Index of UE instance @@ -486,7 +537,9 @@ void ue_get_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t su @param New_Msg3 Flag to indicate this call is for a new Msg3 @param subframe Index of subframe for PRACH transmission (0 ... 9) @returns A pointer to a PRACH_RESOURCES_t */ -PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t new_Msg3,sub_frame_t subframe); +PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, + frame_t frameP, uint8_t new_Msg3, + sub_frame_t subframe); /* \brief Function called by PHY to process the received RAR. It checks that the preamble matches what was sent by the eNB and provides the timing advance and t-CRNTI. @param Mod_id Index of UE instance @@ -501,16 +554,14 @@ random-access procedure @returns timing advance or 0xffff if preamble doesn't match */ uint16_t -ue_process_rar( - const module_id_t module_idP, - const int CC_id, - const frame_t frameP, - const rnti_t ra_rnti, - uint8_t * const dlsch_buffer, - rnti_t * const t_crnti, - const uint8_t preamble_index, - uint8_t* selected_rar_buffer -); +ue_process_rar(const module_id_t module_idP, + const int CC_id, + const frame_t frameP, + const rnti_t ra_rnti, + uint8_t * const dlsch_buffer, + rnti_t * const t_crnti, + const uint8_t preamble_index, + uint8_t * selected_rar_buffer); /* \brief Generate header for UL-SCH. This function parses the desired control elements and sdus and generates the header as described @@ -529,17 +580,17 @@ in the ULSCH buffer. @param post_padding Number of bytes for padding at the end of MAC PDU @returns Number of bytes used for header */ -unsigned char generate_ulsch_header(uint8_t *mac_header, - uint8_t num_sdus, - uint8_t short_padding, - uint16_t *sdu_lengths, - uint8_t *sdu_lcids, - POWER_HEADROOM_CMD *power_headroom, - uint16_t *crnti, - BSR_SHORT *truncated_bsr, - BSR_SHORT *short_bsr, - BSR_LONG *long_bsr, - unsigned short post_padding); +unsigned char generate_ulsch_header(uint8_t * mac_header, + uint8_t num_sdus, + uint8_t short_padding, + uint16_t * sdu_lengths, + uint8_t * sdu_lcids, + POWER_HEADROOM_CMD * power_headroom, + uint16_t * crnti, + BSR_SHORT * truncated_bsr, + BSR_SHORT * short_bsr, + BSR_LONG * long_bsr, + unsigned short post_padding); /* \brief Parse header for UL-SCH. This function parses the received UL-SCH header as described in 36-321 MAC layer specifications. It returns the number of bytes used for the header to be used as an offset for the payload @@ -552,40 +603,46 @@ in the ULSCH buffer. @param rx_lengths Pointer to array of SDU lengths @returns Pointer to payload following header */ -uint8_t *parse_ulsch_header(uint8_t *mac_header, - uint8_t *num_ce, - uint8_t *num_sdu, - uint8_t *rx_ces, - uint8_t *rx_lcids, - uint16_t *rx_lengths, - uint16_t tx_lenght); +uint8_t *parse_ulsch_header(uint8_t * mac_header, + uint8_t * num_ce, + uint8_t * num_sdu, + uint8_t * rx_ces, + uint8_t * rx_lcids, + uint16_t * rx_lengths, uint16_t tx_lenght); int to_prb(int); int to_rbg(int); -int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); +int l2_init(LTE_DL_FRAME_PARMS * frame_parms, int eMBMS_active, + char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); int mac_init(void); -int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti,int harq_pid - #ifdef Rel14 - ,uint8_t rach_resource_type - #endif - ); +int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid +#ifdef Rel14 + , uint8_t rach_resource_type +#endif + ); int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); -int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag); -void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag); -int prev(UE_list_t *listP, int nodeP, int ul_flag); -void dump_ue_list(UE_list_t *listP, int ul_flag); -int UE_num_active_CC(UE_list_t *listP,int ue_idP); -int UE_PCCID(module_id_t mod_idP,int ue_idP); +int maxround(module_id_t Mod_id, uint16_t rnti, int frame, + sub_frame_t subframe, uint8_t ul_flag); +void swap_UEs(UE_list_t * listP, int nodeiP, int nodejP, int ul_flag); +int prev(UE_list_t * listP, int nodeP, int ul_flag); +void dump_ue_list(UE_list_t * listP, int ul_flag); +int UE_num_active_CC(UE_list_t * listP, int ue_idP); +int UE_PCCID(module_id_t mod_idP, int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); -void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb); -void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP); -void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP); -void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP,uint16_t *first_rb); -void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template); +void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, + sub_frame_t subframeP, + uint16_t * first_rb); +void store_ulsch_buffer(module_id_t module_idP, int frameP, + sub_frame_t subframeP); +void sort_ue_ul(module_id_t module_idP, int frameP, sub_frame_t subframeP); +void assign_max_mcs_min_rb(module_id_t module_idP, int frameP, + sub_frame_t subframeP, uint16_t * first_rb); +void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, + UE_TEMPLATE * UE_template); int phy_stats_exist(module_id_t Mod_id, int rnti); /*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index) @@ -599,15 +656,13 @@ int phy_stats_exist(module_id_t Mod_id, int rnti); \param[in] eNB_index instance of eNB @returns L2 state (CONNETION_OK or CONNECTION_LOST or PHY_RESYNCH) */ -UE_L2_STATE_t ue_scheduler( - const module_id_t module_idP, - const frame_t rxFrameP, - const sub_frame_t rxSubframe, - const frame_t txFrameP, - const sub_frame_t txSubframe, - const lte_subframe_t direction, - const uint8_t eNB_index, - const int CC_id); +UE_L2_STATE_t ue_scheduler(const module_id_t module_idP, + const frame_t rxFrameP, + const sub_frame_t rxSubframe, + const frame_t txFrameP, + const sub_frame_t txSubframe, + const lte_subframe_t direction, + const uint8_t eNB_index, const int CC_id); /*! \fn int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen); \brief determine whether to use cba resource to transmit or not @@ -617,7 +672,8 @@ UE_L2_STATE_t ue_scheduler( \param[in] eNB_index instance of eNB \param[out] access(1) or postpone (0) */ -int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen); +int cba_access(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, uint16_t buflen); /*! \fn BSR_SHORT * get_bsr_short(module_id_t module_idP, uint8_t bsr_len) \brief get short bsr level @@ -633,14 +689,15 @@ BSR_SHORT *get_bsr_short(module_id_t module_idP, uint8_t bsr_len); \param[in] bsr_len indicator for no, short, or long bsr \param[out] bsr_l pointer to long bsr */ -BSR_LONG * get_bsr_long(module_id_t module_idP, uint8_t bsr_len); +BSR_LONG *get_bsr_long(module_id_t module_idP, uint8_t bsr_len); /*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP) \brief get the rlc stats and update the bsr level for each lcid \param[in] Mod_id instance of the UE \param[in] frame Frame index */ -boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index); +boolean_t update_bsr(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP, eNB_index_t eNB_index); /*! \fn locate_BsrIndexByBufferSize (int *table, int size, int value) \brief locate the BSR level in the table as defined in 36.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table. @@ -649,7 +706,8 @@ boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subfram \param[in] value Value of the buffer \return the index in the BSR_LEVEL table */ -uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value); +uint8_t locate_BsrIndexByBufferSize(const uint32_t * table, int size, + int value); /*! \fn int get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer) @@ -700,7 +758,8 @@ int get_db_dl_PathlossChange(uint8_t dl_PathlossChange); \param[in] CC_id Component Carrier Index \return phr mapping */ -uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index); +uint8_t get_phr_mapping(module_id_t module_idP, int CC_id, + uint8_t eNB_index); /*! \fn void update_phr (module_id_t module_idP) \brief update/reset the phr timers @@ -708,13 +767,14 @@ uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index); \param[in] CC_id Component carrier index \return void */ -void update_phr (module_id_t module_idP,int CC_id); +void update_phr(module_id_t module_idP, int CC_id); /*! \brief Function to indicate Msg3 transmission/retransmission which initiates/reset Contention Resolution Timer \param[in] Mod_id Instance index of UE \param[in] eNB_id Index of eNB */ -void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP,uint8_t eNB_id); +void Msg3_tx(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + uint8_t eNB_id); /*! \brief Function to indicate the transmission of msg1/rach @@ -722,12 +782,12 @@ void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP,uint8_t eNB_id) \param[in] eNB_id Index of eNB */ -void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id); +void Msg1_tx(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + uint8_t eNB_id); -void dl_phy_sync_success(module_id_t module_idP, - frame_t frameP, - unsigned char eNB_index, - uint8_t first_sync); +void dl_phy_sync_success(module_id_t module_idP, + frame_t frameP, + unsigned char eNB_index, uint8_t first_sync); int dump_eNB_l2_stats(char *buffer, int length); @@ -744,9 +804,11 @@ void add_common_dci(DCI_PDU *DCI_pdu, uint8_t ra_flag); */ -uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t *rballoc); +uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, + uint8_t * rballoc); -void update_ul_dci(module_id_t module_idP,uint8_t CC_id,rnti_t rnti,uint8_t dai); +void update_ul_dci(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, + uint8_t dai); int get_bw_index(module_id_t module_id, uint8_t CC_id); @@ -767,14 +829,14 @@ in the DLSCH buffer. @returns Number of bytes used for header */ 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, - unsigned short timing_advance_cmd, - unsigned char *ue_cont_res_id, - unsigned char short_padding, - unsigned short post_padding); + unsigned char num_sdus, + unsigned short *sdu_lengths, + unsigned char *sdu_lcids, + unsigned char drx_cmd, + unsigned short timing_advance_cmd, + unsigned char *ue_cont_res_id, + unsigned char short_padding, + unsigned short post_padding); /** \brief RRC eNB Configuration primitive for PHY/MAC. Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages. @param Mod_id Instance ID of eNB @@ -798,51 +860,55 @@ unsigned char generate_dlsch_header(unsigned char *mac_header, @param sib1_ext_r13 SI Scheduling information for SI-BR UEs */ -int rrc_mac_config_req_eNB(module_id_t module_idP, - int CC_id, - int physCellId, - int p_eNB, - int Ncp, - int eutra_band, - uint32_t dl_CarrierFreq, +int rrc_mac_config_req_eNB(module_id_t module_idP, + int CC_id, + int physCellId, + int p_eNB, + int Ncp, + int eutra_band, uint32_t dl_CarrierFreq, #ifdef Rel14 - int pbch_repetition, + int pbch_repetition, #endif - rnti_t rntiP, - BCCH_BCH_Message_t *mib, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, + rnti_t rntiP, + BCCH_BCH_Message_t * mib, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon, #ifdef Rel14 - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon_BR, #endif - struct PhysicalConfigDedicated *physicalConfigDedicated, + struct PhysicalConfigDedicated + *physicalConfigDedicated, #if defined(Rel10) || defined(Rel14) - SCellToAddMod_r10_t *sCellToAddMod_r10, + SCellToAddMod_r10_t * sCellToAddMod_r10, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif - MeasObjectToAddMod_t **measObj, - MAC_MainConfig_t *mac_MainConfig, - long logicalChannelIdentity, - LogicalChannelConfig_t *logicalChannelConfig, - MeasGapConfig_t *measGapConfig, - TDD_Config_t *tdd_Config, - MobilityControlInfo_t *mobilityControlInfo, - SchedulingInfoList_t *schedulingInfoList, - uint32_t ul_CarrierFreq, - long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList + MeasObjectToAddMod_t ** measObj, + MAC_MainConfig_t * mac_MainConfig, + long logicalChannelIdentity, + LogicalChannelConfig_t * logicalChannelConfig, + MeasGapConfig_t * measGapConfig, + TDD_Config_t * tdd_Config, + MobilityControlInfo_t * mobilityControlInfo, + SchedulingInfoList_t * schedulingInfoList, + uint32_t ul_CarrierFreq, + long *ul_Bandwidth, + AdditionalSpectrumEmission_t * + additionalSpectrumEmission, + struct MBSFN_SubframeConfigList + *mbsfn_SubframeConfigList #if defined(Rel10) || defined(Rel14) , - uint8_t MBMS_Flag, - MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, - PMCH_InfoList_r9_t *pmch_InfoList - + uint8_t MBMS_Flag, + MBSFN_AreaInfoList_r9_t * mbsfn_AreaInfoList, + PMCH_InfoList_r9_t * pmch_InfoList #endif #ifdef Rel14 , - SystemInformationBlockType1_v1310_IEs_t *sib1_ext_r13 + SystemInformationBlockType1_v1310_IEs_t * + sib1_ext_r13 #endif - ); + ); /** \brief RRC eNB Configuration primitive for PHY/MAC. Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages. @param Mod_id Instance ID of ue @@ -864,132 +930,154 @@ int rrc_mac_config_req_eNB(module_id_t module_idP, @param mbsfn_AreaInfoList pointer to MBSFN Area Info list from SIB13 @param pmch_InfoList pointer to PMCH_InfoList from MBSFNAreaConfiguration Message (MCCH Message) */ -int rrc_mac_config_req_ue(module_id_t module_idP, - int CC_id, - uint8_t eNB_index, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, - struct PhysicalConfigDedicated *physicalConfigDedicated, +int rrc_mac_config_req_ue(module_id_t module_idP, + int CC_id, + uint8_t eNB_index, + RadioResourceConfigCommonSIB_t * + radioResourceConfigCommon, + struct PhysicalConfigDedicated + *physicalConfigDedicated, #if defined(Rel10) || defined(Rel14) - SCellToAddMod_r10_t *sCellToAddMod_r10, + SCellToAddMod_r10_t * sCellToAddMod_r10, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif - MeasObjectToAddMod_t **measObj, - MAC_MainConfig_t *mac_MainConfig, + MeasObjectToAddMod_t ** measObj, + MAC_MainConfig_t * mac_MainConfig, long logicalChannelIdentity, - LogicalChannelConfig_t *logicalChannelConfig, - MeasGapConfig_t *measGapConfig, - TDD_Config_t *tdd_Config, - MobilityControlInfo_t *mobilityControlInfo, - uint8_t *SIwindowsize, - uint16_t *SIperiod, - ARFCN_ValueEUTRA_t *ul_CarrierFreq, + LogicalChannelConfig_t * logicalChannelConfig, + MeasGapConfig_t * measGapConfig, + TDD_Config_t * tdd_Config, + MobilityControlInfo_t * mobilityControlInfo, + uint8_t * SIwindowsize, + uint16_t * SIperiod, + ARFCN_ValueEUTRA_t * ul_CarrierFreq, long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList + AdditionalSpectrumEmission_t * + additionalSpectrumEmission, + struct MBSFN_SubframeConfigList + *mbsfn_SubframeConfigList #if defined(Rel10) || defined(Rel14) , uint8_t MBMS_Flag, - MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, - PMCH_InfoList_r9_t *pmch_InfoList - + MBSFN_AreaInfoList_r9_t * mbsfn_AreaInfoList, + PMCH_InfoList_r9_t * pmch_InfoList #endif #ifdef CBA , - uint8_t num_active_cba_groups, - uint16_t cba_rnti + uint8_t num_active_cba_groups, uint16_t cba_rnti #endif - ); + ); -uint16_t getRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); +uint16_t getRIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); int get_subbandsize(uint8_t dl_bandwidth); -void get_Msg3allocret(COMMON_channels_t *cc, +void get_Msg3allocret(COMMON_channels_t * cc, sub_frame_t current_subframe, frame_t current_frame, - frame_t *frame, - sub_frame_t *subframe); + frame_t * frame, sub_frame_t * subframe); -void get_Msg3alloc(COMMON_channels_t *cc, +void get_Msg3alloc(COMMON_channels_t * cc, sub_frame_t current_subframe, frame_t current_frame, - frame_t *frame, - sub_frame_t *subframe); + frame_t * frame, sub_frame_t * subframe); -uint16_t mac_computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); +uint16_t mac_computeRIV(uint16_t N_RB_DL, uint16_t RBstart, + uint16_t Lcrbs); -int get_phich_resource_times6(COMMON_channels_t *cc); +int get_phich_resource_times6(COMMON_channels_t * cc); int to_rbg(int dl_Bandwidth); int to_prb(int dl_Bandwidth); -uint8_t get_Msg3harqpid(COMMON_channels_t *cc, - frame_t frame, - sub_frame_t current_subframe); +uint8_t get_Msg3harqpid(COMMON_channels_t * cc, + frame_t frame, sub_frame_t current_subframe); -uint32_t pdcchalloc2ulframe(COMMON_channels_t *ccP,uint32_t frame, uint8_t n); +uint32_t pdcchalloc2ulframe(COMMON_channels_t * ccP, uint32_t frame, + uint8_t n); -uint8_t pdcchalloc2ulsubframe(COMMON_channels_t *ccP,uint8_t n); +uint8_t pdcchalloc2ulsubframe(COMMON_channels_t * ccP, uint8_t n); -int is_UL_sf(COMMON_channels_t *ccP,sub_frame_t subframeP); +int is_UL_sf(COMMON_channels_t * ccP, sub_frame_t subframeP); uint8_t getQm(uint8_t mcs); -uint8_t subframe2harqpid(COMMON_channels_t *cc,frame_t frame,sub_frame_t subframe); - -void get_srs_pos(COMMON_channels_t *cc,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset); - -void get_csi_params(COMMON_channels_t *cc,struct CQI_ReportPeriodic *cqi_PMI_ConfigIndex,uint16_t *Npd,uint16_t *N_OFFSET_CQI,int *H); - -uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl *sched_ctl,int CC_idP,COMMON_channels_t *cc,uint8_t tmode, struct CQI_ReportPeriodic *cqi_ReportPeriodic); - -uint8_t get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc,uint8_t tmode, uint8_t ri, CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic); -void extract_pucch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP, uint8_t *pdu, uint8_t length); - -void extract_pusch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP,uint8_t *pdu, uint8_t length); - -uint16_t fill_nfapi_tx_req(nfapi_tx_request_body_t *tx_req_body,uint16_t absSF,uint16_t pdu_length, uint16_t pdu_index, uint8_t *pdu ); - -void fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t *ul_config_pdu, - uint8_t cqi_req, - COMMON_channels_t *cc, - struct PhysicalConfigDedicated *physicalConfigDedicated, - uint8_t tmode, - uint32_t handle, - uint16_t rnti, - uint8_t resource_block_start, - uint8_t number_of_resource_blocks, - uint8_t mcs, - uint8_t cyclic_shift_2_for_drms, - uint8_t frequency_hopping_enabled_flag, - uint8_t frequency_hopping_bits, - uint8_t new_data_indication, - uint8_t redundancy_version, - uint8_t harq_process_number, - uint8_t ul_tx_mode, - uint8_t current_tx_nb, - uint8_t n_srs, - uint16_t size - ); +uint8_t subframe2harqpid(COMMON_channels_t * cc, frame_t frame, + sub_frame_t subframe); + +void get_srs_pos(COMMON_channels_t * cc, uint16_t isrs, + uint16_t * psrsPeriodicity, uint16_t * psrsOffset); + +void get_csi_params(COMMON_channels_t * cc, + struct CQI_ReportPeriodic *cqi_PMI_ConfigIndex, + uint16_t * Npd, uint16_t * N_OFFSET_CQI, int *H); + +uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl * sched_ctl, int CC_idP, + COMMON_channels_t * cc, uint8_t tmode, + struct CQI_ReportPeriodic + *cqi_ReportPeriodic); + +uint8_t get_dl_cqi_pmi_size_pusch(COMMON_channels_t * cc, uint8_t tmode, + uint8_t ri, + CQI_ReportModeAperiodic_t * + cqi_ReportModeAperiodic); +void extract_pucch_csi(module_id_t mod_idP, int CC_idP, int UE_id, + frame_t frameP, sub_frame_t subframeP, + uint8_t * pdu, uint8_t length); + +void extract_pusch_csi(module_id_t mod_idP, int CC_idP, int UE_id, + frame_t frameP, sub_frame_t subframeP, + uint8_t * pdu, uint8_t length); + +uint16_t fill_nfapi_tx_req(nfapi_tx_request_body_t * tx_req_body, + uint16_t absSF, uint16_t pdu_length, + uint16_t pdu_index, uint8_t * pdu); + +void fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t * + ul_config_pdu, uint8_t cqi_req, + COMMON_channels_t * cc, + struct PhysicalConfigDedicated + *physicalConfigDedicated, + uint8_t tmode, uint32_t handle, + uint16_t rnti, + uint8_t resource_block_start, + uint8_t + number_of_resource_blocks, + uint8_t mcs, + uint8_t cyclic_shift_2_for_drms, + uint8_t + frequency_hopping_enabled_flag, + uint8_t frequency_hopping_bits, + uint8_t new_data_indication, + uint8_t redundancy_version, + uint8_t harq_process_number, + uint8_t ul_tx_mode, + uint8_t current_tx_nb, + uint8_t n_srs, uint16_t size); #ifdef Rel14 -void fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t *ul_config_pdu, - uint8_t ue_type, - uint16_t total_number_of_repetitions, +void fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t * + ul_config_pdu, uint8_t ue_type, + uint16_t + total_number_of_repetitions, uint16_t repetition_number, - uint16_t initial_transmission_sf_io); + uint16_t + initial_transmission_sf_io); #endif -void program_dlsch_acknak(module_id_t module_idP, int CC_idP,int UE_idP, frame_t frameP, sub_frame_t subframeP,uint8_t cce_idx); +void program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP, + frame_t frameP, sub_frame_t subframeP, + uint8_t cce_idx); -void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, nfapi_dl_config_request_body_t *dl_req, - uint16_t length, - uint16_t pdu_index, +void fill_nfapi_dlsch_config(eNB_MAC_INST * eNB, + nfapi_dl_config_request_body_t * dl_req, + uint16_t length, uint16_t pdu_index, uint16_t rnti, uint8_t resource_allocation_type, - uint8_t virtual_resource_block_assignment_flag, + uint8_t + virtual_resource_block_assignment_flag, uint16_t resource_block_coding, uint8_t modulation, uint8_t redundancy_version, @@ -998,7 +1086,7 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, nfapi_dl_config_request_body_t * uint8_t transmission_scheme, uint8_t number_of_layers, uint8_t number_of_subbands, - // uint8_t codebook_index, + // uint8_t codebook_index, uint8_t ue_category_capacity, uint8_t pa, uint8_t delta_power_offset_index, @@ -1006,28 +1094,27 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, nfapi_dl_config_request_body_t * uint8_t nprb, uint8_t transmission_mode, uint8_t num_bf_prb_per_subband, - uint8_t num_bf_vector - ); + uint8_t num_bf_vector); void fill_nfapi_harq_information(module_id_t module_idP, int CC_idP, uint16_t rntiP, uint16_t absSFP, - nfapi_ul_config_harq_information *harq_information, - uint8_t cce_idxP); + nfapi_ul_config_harq_information * + harq_information, uint8_t cce_idxP); void fill_nfapi_ulsch_harq_information(module_id_t module_idP, int CC_idP, uint16_t rntiP, - nfapi_ul_config_ulsch_harq_information *harq_information); + nfapi_ul_config_ulsch_harq_information + * harq_information); uint16_t fill_nfapi_uci_acknak(module_id_t module_idP, int CC_idP, uint16_t rntiP, - uint16_t absSFP, - uint8_t cce_idxP); + uint16_t absSFP, uint8_t cce_idxP); -void fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t *dl_config_pdu, +void fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t * dl_config_pdu, uint8_t aggregation_level, uint16_t rnti, uint8_t rnti_type, @@ -1035,34 +1122,40 @@ void fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t tpc, uint16_t resource_block_coding, uint8_t mcs, - uint8_t ndi, - uint8_t rv, - uint8_t vrb_flag); + uint8_t ndi, uint8_t rv, uint8_t vrb_flag); -nfapi_ul_config_request_pdu_t* has_ul_grant(module_id_t module_idP,int CC_idP,uint16_t subframeP,uint16_t rnti); +nfapi_ul_config_request_pdu_t *has_ul_grant(module_id_t module_idP, + int CC_idP, uint16_t subframeP, + uint16_t rnti); -uint8_t get_tmode(module_id_t module_idP,int CC_idP,int UE_idP); +uint8_t get_tmode(module_id_t module_idP, int CC_idP, int UE_idP); -uint8_t get_ul_req_index(module_id_t module_idP, int CC_idP, sub_frame_t subframeP); +uint8_t get_ul_req_index(module_id_t module_idP, int CC_idP, + sub_frame_t subframeP); #ifdef Rel14 int get_numnarrowbandbits(long dl_Bandwidth); -int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type,int UE_id); +int mpdcch_sf_condition(eNB_MAC_INST * eNB, int CC_id, frame_t frameP, + sub_frame_t subframeP, int rmax, + MPDCCH_TYPES_t mpdcch_type, int UE_id); int get_numnarrowbands(long dl_Bandwidth); -int narrowband_to_first_rb(COMMON_channels_t *cc, int nb_index); +int narrowband_to_first_rb(COMMON_channels_t * cc, int nb_index); #endif int l2_init_eNB(void); -void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id); -void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id); -uint32_t from_earfcn(int eutra_bandP,uint32_t dl_earfcn); +void Msg1_transmitted(module_id_t module_idP, uint8_t CC_id, + frame_t frameP, uint8_t eNB_id); +void Msg3_transmitted(module_id_t module_idP, uint8_t CC_id, + frame_t frameP, uint8_t eNB_id); +uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn); int32_t get_uldl_offset(int eutra_bandP); -int l2_init_ue(int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active); +int l2_init_ue(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, + uint8_t HO_active); #endif /** @}*/ diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c index f649acad1ea1fcc21bed1dad0e3f3e66c01d0d70..3f2df025c773db688fd255b1439d86dcb15e4478 100644 --- a/openair2/LAYER2/MAC/ra_procedures.c +++ b/openair2/LAYER2/MAC/ra_procedures.c @@ -47,482 +47,604 @@ #include "SIMULATION/simulation_defs.h" #endif -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus -int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id) +int8_t get_DELTA_PREAMBLE(module_id_t module_idP, int CC_id) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - uint8_t prachConfigIndex = UE_mac_inst[module_idP].radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - uint8_t preambleformat; - - if (UE_mac_inst[module_idP].tdd_Config) { // TDD - if (prachConfigIndex < 20) { - preambleformat = 0; - } else if (prachConfigIndex < 30) { - preambleformat = 1; - } else if (prachConfigIndex < 40) { - preambleformat = 2; - } else if (prachConfigIndex < 48) { - preambleformat = 3; - } else { - preambleformat = 4; + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + uint8_t prachConfigIndex = + UE_mac_inst[module_idP].radioResourceConfigCommon-> + prach_Config.prach_ConfigInfo.prach_ConfigIndex; + uint8_t preambleformat; + + if (UE_mac_inst[module_idP].tdd_Config) { // TDD + if (prachConfigIndex < 20) { + preambleformat = 0; + } else if (prachConfigIndex < 30) { + preambleformat = 1; + } else if (prachConfigIndex < 40) { + preambleformat = 2; + } else if (prachConfigIndex < 48) { + preambleformat = 3; + } else { + preambleformat = 4; + } + } else { // FDD + preambleformat = prachConfigIndex >> 2; } - } else { // FDD - preambleformat = prachConfigIndex>>2; - } - switch (preambleformat) { - case 0: - case 1: - return(0); + switch (preambleformat) { + case 0: + case 1: + return (0); - case 2: - case 3: - return(-3); + case 2: + case 3: + return (-3); - case 4: - return(8); + case 4: + return (8); - default: - AssertFatal(1==0,"[UE %d] ue_procedures.c: FATAL, Illegal preambleformat %d, prachConfigIndex %d\n", - module_idP, - preambleformat,prachConfigIndex); - } + default: + AssertFatal(1 == 0, + "[UE %d] ue_procedures.c: FATAL, Illegal preambleformat %d, prachConfigIndex %d\n", + module_idP, preambleformat, prachConfigIndex); + } } /// This routine implements Section 5.1.2 (UE Random Access Resource Selection) from 36.321 -void get_prach_resources(module_id_t module_idP, - int CC_id, - uint8_t eNB_index, - uint8_t t_id, - uint8_t first_Msg3, - RACH_ConfigDedicated_t *rach_ConfigDedicated) +void +get_prach_resources(module_id_t module_idP, + int CC_id, + uint8_t eNB_index, + uint8_t t_id, + uint8_t first_Msg3, + RACH_ConfigDedicated_t * rach_ConfigDedicated) { - uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size; - PRACH_RESOURCES_t *prach_resources = &UE_mac_inst[module_idP].RA_prach_resources; - RACH_ConfigCommon_t *rach_ConfigCommon = NULL; - uint8_t noGroupB = 0; - uint8_t f_id = 0,num_prach=0; - int numberOfRA_Preambles; - int messageSizeGroupA; - int sizeOfRA_PreamblesGroupA; - int messagePowerOffsetGroupB; - int PLThreshold; - - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon!=NULL, - "[UE %d] FATAL radioResourceConfigCommon is NULL !!!\n",module_idP); - - rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon; - numberOfRA_Preambles = (1+rach_ConfigCommon->preambleInfo.numberOfRA_Preambles)<<2; - - if (rach_ConfigDedicated) { // This is for network controlled Mobility, later - if (rach_ConfigDedicated->ra_PRACH_MaskIndex != 0) { - prach_resources->ra_PreambleIndex = rach_ConfigDedicated->ra_PreambleIndex; - prach_resources->ra_RACH_MaskIndex = rach_ConfigDedicated->ra_PRACH_MaskIndex; - return; + uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size; + PRACH_RESOURCES_t *prach_resources = + &UE_mac_inst[module_idP].RA_prach_resources; + RACH_ConfigCommon_t *rach_ConfigCommon = NULL; + uint8_t noGroupB = 0; + uint8_t f_id = 0, num_prach = 0; + int numberOfRA_Preambles; + int messageSizeGroupA; + int sizeOfRA_PreamblesGroupA; + int messagePowerOffsetGroupB; + int PLThreshold; + + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon != NULL, + "[UE %d] FATAL radioResourceConfigCommon is NULL !!!\n", + module_idP); + + rach_ConfigCommon = + &UE_mac_inst[module_idP].radioResourceConfigCommon-> + rach_ConfigCommon; + numberOfRA_Preambles = + (1 + rach_ConfigCommon->preambleInfo.numberOfRA_Preambles) << 2; + + if (rach_ConfigDedicated) { // This is for network controlled Mobility, later + if (rach_ConfigDedicated->ra_PRACH_MaskIndex != 0) { + prach_resources->ra_PreambleIndex = + rach_ConfigDedicated->ra_PreambleIndex; + prach_resources->ra_RACH_MaskIndex = + rach_ConfigDedicated->ra_PRACH_MaskIndex; + return; + } } - } - /* TODO: gcc warns if this variable is not always set, let's put -1 for no more warning */ - messageSizeGroupA = -1; + /* TODO: gcc warns if this variable is not always set, let's put -1 for no more warning */ + messageSizeGroupA = -1; - if (!rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) { - noGroupB = 1; - } else { - sizeOfRA_PreamblesGroupA = (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA+1)<<2; - switch (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->messageSizeGroupA) { - case 0: - messageSizeGroupA = 56; - break; - case 1: - messageSizeGroupA = 144; - break; - case 2: - messageSizeGroupA = 208; - break; - case 3: - messageSizeGroupA = 256; - break; - } + if (!rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) { + noGroupB = 1; + } else { + sizeOfRA_PreamblesGroupA = + (rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->sizeOfRA_PreamblesGroupA + 1) << 2; + switch (rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->messageSizeGroupA) { + case 0: + messageSizeGroupA = 56; + break; + case 1: + messageSizeGroupA = 144; + break; + case 2: + messageSizeGroupA = 208; + break; + case 3: + messageSizeGroupA = 256; + break; + } - /* TODO: what value to use as default? */ - messagePowerOffsetGroupB = -9999; - switch (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->messagePowerOffsetGroupB) { - case 0: - messagePowerOffsetGroupB = -9999; - break; - case 1: - messagePowerOffsetGroupB = 0; - break; - case 2: - messagePowerOffsetGroupB = 5; - break; - case 3: - messagePowerOffsetGroupB = 8; - break; - case 4: - messagePowerOffsetGroupB = 10; - break; - case 5: - messagePowerOffsetGroupB = 12; - break; - case 6: - messagePowerOffsetGroupB = 15; - break; - case 7: - messagePowerOffsetGroupB = 18; - break; - } + /* TODO: what value to use as default? */ + messagePowerOffsetGroupB = -9999; + switch (rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->messagePowerOffsetGroupB) { + case 0: + messagePowerOffsetGroupB = -9999; + break; + case 1: + messagePowerOffsetGroupB = 0; + break; + case 2: + messagePowerOffsetGroupB = 5; + break; + case 3: + messagePowerOffsetGroupB = 8; + break; + case 4: + messagePowerOffsetGroupB = 10; + break; + case 5: + messagePowerOffsetGroupB = 12; + break; + case 6: + messagePowerOffsetGroupB = 15; + break; + case 7: + messagePowerOffsetGroupB = 18; + break; + } - PLThreshold = 0 - get_DELTA_PREAMBLE(module_idP,CC_id) - get_Po_NOMINAL_PUSCH(module_idP,CC_id) - messagePowerOffsetGroupB; - // Note Pcmax is set to 0 here, we have to fix this + PLThreshold = + 0 - get_DELTA_PREAMBLE(module_idP, + CC_id) - + get_Po_NOMINAL_PUSCH(module_idP, + CC_id) - messagePowerOffsetGroupB; + // Note Pcmax is set to 0 here, we have to fix this - if (sizeOfRA_PreamblesGroupA == numberOfRA_Preambles) { - noGroupB = 1; - } - } - - if (first_Msg3 == 1) { - if (noGroupB == 1) { - // use Group A procedure - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = (taus())%numberOfRA_Preambles; - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; - UE_mac_inst[module_idP].RA_usedGroupA = 1; - } else if ((Msg3_size <messageSizeGroupA) || - (get_PL(module_idP,0,eNB_index) > PLThreshold)) { - // use Group A procedure - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = (taus())%sizeOfRA_PreamblesGroupA; - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; - UE_mac_inst[module_idP].RA_usedGroupA = 1; - } else { // use Group B - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = sizeOfRA_PreamblesGroupA + - (taus())%(numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; - UE_mac_inst[module_idP].RA_usedGroupA = 0; + if (sizeOfRA_PreamblesGroupA == numberOfRA_Preambles) { + noGroupB = 1; + } } - UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER = get_Po_NOMINAL_PUSCH(module_idP,CC_id); - } else { // Msg3 is being retransmitted - if (UE_mac_inst[module_idP].RA_usedGroupA == 1) { - if (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) { - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = (taus())%rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA; - } else { - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = (taus())&0x3f; - } + if (first_Msg3 == 1) { + if (noGroupB == 1) { + // use Group A procedure + UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = + (taus()) % numberOfRA_Preambles; + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = + 0; + UE_mac_inst[module_idP].RA_usedGroupA = 1; + } else if ((Msg3_size < messageSizeGroupA) || + (get_PL(module_idP, 0, eNB_index) > PLThreshold)) { + // use Group A procedure + UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = + (taus()) % sizeOfRA_PreamblesGroupA; + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = + 0; + UE_mac_inst[module_idP].RA_usedGroupA = 1; + } else { // use Group B + UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = + sizeOfRA_PreamblesGroupA + + (taus()) % (numberOfRA_Preambles - + sizeOfRA_PreamblesGroupA); + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = + 0; + UE_mac_inst[module_idP].RA_usedGroupA = 0; + } - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; - } else { - // FIXME rach_ConfigCommon->preambleInfo.preamblesGroupAConfig may be zero - UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = - rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA + - (taus())%(rach_ConfigCommon->preambleInfo.numberOfRA_Preambles - - rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA); - UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0; + UE_mac_inst[module_idP]. + RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER = + get_Po_NOMINAL_PUSCH(module_idP, CC_id); + } else { // Msg3 is being retransmitted + if (UE_mac_inst[module_idP].RA_usedGroupA == 1) { + if (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) { + UE_mac_inst[module_idP].RA_prach_resources. + ra_PreambleIndex = + (taus()) % + rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->sizeOfRA_PreamblesGroupA; + } else { + UE_mac_inst[module_idP].RA_prach_resources. + ra_PreambleIndex = (taus()) & 0x3f; + } + + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = + 0; + } else { + // FIXME rach_ConfigCommon->preambleInfo.preamblesGroupAConfig may be zero + UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex = + rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->sizeOfRA_PreamblesGroupA + + (taus()) % + (rach_ConfigCommon->preambleInfo.numberOfRA_Preambles - + rach_ConfigCommon->preambleInfo. + preamblesGroupAConfig->sizeOfRA_PreamblesGroupA); + UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = + 0; + } } - } - - // choose random PRACH resource in TDD - if (UE_mac_inst[module_idP].tdd_Config) { - num_prach = get_num_prach_tdd(module_idP); - if ((num_prach>0) && (num_prach<6)) { - UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index = (taus()%num_prach); - } + // choose random PRACH resource in TDD + if (UE_mac_inst[module_idP].tdd_Config) { + num_prach = get_num_prach_tdd(module_idP); - f_id = get_fid_prach_tdd(module_idP, - UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index); - } + if ((num_prach > 0) && (num_prach < 6)) { + UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index = + (taus() % num_prach); + } - // choose RA-RNTI - UE_mac_inst[module_idP].RA_prach_resources.ra_RNTI = 1 + t_id + 10*f_id; + f_id = get_fid_prach_tdd(module_idP, + UE_mac_inst + [module_idP].RA_prach_resources. + ra_TDD_map_index); + } + // choose RA-RNTI + UE_mac_inst[module_idP].RA_prach_resources.ra_RNTI = + 1 + t_id + 10 * f_id; } -void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id) +void +Msg1_transmitted(module_id_t module_idP, uint8_t CC_id, + frame_t frameP, uint8_t eNB_id) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - // start contention resolution timer - UE_mac_inst[module_idP].RA_attempt_number++; - - if (opt_enabled) { - trace_pdu(0, NULL, 0, module_idP, 0 , UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex, - UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, UE_mac_inst[module_idP].RA_attempt_number); - LOG_D(OPT,"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x with size %d\n", - module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size); - } + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + // start contention resolution timer + UE_mac_inst[module_idP].RA_attempt_number++; + + if (opt_enabled) { + trace_pdu(0, NULL, 0, module_idP, 0, + UE_mac_inst[module_idP].RA_prach_resources. + ra_PreambleIndex, UE_mac_inst[module_idP].txFrame, + UE_mac_inst[module_idP].txSubframe, 0, + UE_mac_inst[module_idP].RA_attempt_number); + LOG_D(OPT, + "[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x with size %d\n", + module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size); + } } -void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id) +void +Msg3_transmitted(module_id_t module_idP, uint8_t CC_id, + frame_t frameP, uint8_t eNB_id) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - - // start contention resolution timer - LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n",module_idP,frameP); - UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0; - UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1; - - if (opt_enabled) { // msg3 - trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size, - module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0); - LOG_D(OPT,"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d with size %d\n", - module_idP, frameP, UE_mac_inst[module_idP].crnti /*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex*/, UE_mac_inst[module_idP].RA_Msg3_size); - } + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + + // start contention resolution timer + LOG_D(MAC, + "[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n", + module_idP, frameP); + UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0; + UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1; + + if (opt_enabled) { // msg3 + trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], + UE_mac_inst[module_idP].RA_Msg3_size, module_idP, 3, + UE_mac_inst[module_idP].crnti, + UE_mac_inst[module_idP].txFrame, + UE_mac_inst[module_idP].txSubframe, 0, 0); + LOG_D(OPT, + "[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d with size %d\n", + module_idP, frameP, UE_mac_inst[module_idP].crnti + /*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex */ + , UE_mac_inst[module_idP].RA_Msg3_size); + } } -PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_indexP,sub_frame_t subframeP) +PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, + frame_t frameP, uint8_t eNB_indexP, + sub_frame_t subframeP) { - uint8_t Size = 0; - UE_MODE_t UE_mode = get_ue_mode(module_idP,0,eNB_indexP); - uint8_t lcid = CCCH; - uint16_t Size16; - struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL; - int32_t frame_diff = 0; - mac_rlc_status_resp_t rlc_status; - uint8_t dcch_header_len = 0; - uint16_t sdu_lengths[8]; - uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES]; - - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - - if (UE_mode == PRACH) { - if (UE_mac_inst[module_idP].radioResourceConfigCommon) { - rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon; - } else { - return(NULL); - } - - if (UE_mac_inst[module_idP].RA_active == 0) { - LOG_I(MAC,"RA not active\n"); - // check if RRC is ready to initiate the RA procedure - Size = mac_rrc_data_req(module_idP, - CC_id, - frameP, - CCCH,1, - &UE_mac_inst[module_idP].CCCH_pdu.payload[sizeof(SCH_SUBHEADER_SHORT)+1],0, - eNB_indexP, - 0); - Size16 = (uint16_t)Size; - - // LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size); - LOG_I(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_DATA_REQ (RRCConnectionRequest eNB %d) --->][MAC_UE][MOD %02d][]\n", - frameP, module_idP, eNB_indexP, module_idP); - LOG_I(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size); - - if (Size>0) { - - UE_mac_inst[module_idP].RA_active = 1; - UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - UE_mac_inst[module_idP].RA_Msg3_size = Size+sizeof(SCH_SUBHEADER_SHORT)+sizeof(SCH_SUBHEADER_SHORT); - UE_mac_inst[module_idP].RA_prachMaskIndex = 0; - UE_mac_inst[module_idP].RA_prach_resources.Msg3 = UE_mac_inst[module_idP].CCCH_pdu.payload; - UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) - - AssertFatal(rach_ConfigCommon!=NULL, - "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP); - UE_mac_inst[module_idP].RA_window_cnt = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize; - - if (UE_mac_inst[module_idP].RA_window_cnt == 9) { - UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10! + uint8_t Size = 0; + UE_MODE_t UE_mode = get_ue_mode(module_idP, 0, eNB_indexP); + uint8_t lcid = CCCH; + uint16_t Size16; + struct RACH_ConfigCommon *rach_ConfigCommon = + (struct RACH_ConfigCommon *) NULL; + int32_t frame_diff = 0; + mac_rlc_status_resp_t rlc_status; + uint8_t dcch_header_len = 0; + uint16_t sdu_lengths[8]; + uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES]; + + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + + if (UE_mode == PRACH) { + if (UE_mac_inst[module_idP].radioResourceConfigCommon) { + rach_ConfigCommon = + &UE_mac_inst[module_idP]. + radioResourceConfigCommon->rach_ConfigCommon; + } else { + return (NULL); } - - UE_mac_inst[module_idP].RA_tx_frame = frameP; - UE_mac_inst[module_idP].RA_tx_subframe = subframeP; - UE_mac_inst[module_idP].RA_backoff_frame = frameP; - UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; - // Fill in preamble and PRACH resource - get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,1,NULL); - - generate_ulsch_header((uint8_t*)&UE_mac_inst[module_idP].CCCH_pdu.payload[0], // mac header - 1, // num sdus - 0, // short pading - &Size16, // sdu length - &lcid, // sdu lcid - NULL, // power headroom - NULL, // crnti - NULL, // truncated bsr - NULL, // short bsr - NULL, // long_bsr - 1); //post_padding - return(&UE_mac_inst[module_idP].RA_prach_resources); - - } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) { - // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example) - dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element - rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, - DCCH, - 6); - - if (UE_mac_inst[module_idP].crnti_before_ho) - LOG_D(MAC, - "[UE %d] Frame %d : UL-DCCH -> ULSCH, HO RRCConnectionReconfigurationComplete (%x, %x), RRC message has %d bytes to send throug PRACH (mac header len %d)\n", - module_idP,frameP, UE_mac_inst[module_idP].crnti,UE_mac_inst[module_idP].crnti_before_ho, rlc_status.bytes_in_buffer,dcch_header_len); - else - LOG_D(MAC,"[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to send through PRACH(mac header len %d)\n", - module_idP,frameP, rlc_status.bytes_in_buffer,dcch_header_len); - - sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, - eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO, - DCCH, - 6, //not used - (char *)&ulsch_buff[0]); - - LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]); - update_bsr(module_idP, frameP, subframeP,eNB_indexP); - UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] = - locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]]); - - //TO DO: fill BSR infos in UL TBS - - //header_len +=2; - UE_mac_inst[module_idP].RA_active = 1; - UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - UE_mac_inst[module_idP].RA_Msg3_size = Size+dcch_header_len; - UE_mac_inst[module_idP].RA_prachMaskIndex = 0; - UE_mac_inst[module_idP].RA_prach_resources.Msg3 = ulsch_buff; - UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) - - AssertFatal(rach_ConfigCommon!=NULL, - "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP); - UE_mac_inst[module_idP].RA_window_cnt = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize; - - if (UE_mac_inst[module_idP].RA_window_cnt == 9) { - UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10! - } - - - UE_mac_inst[module_idP].RA_tx_frame = frameP; - UE_mac_inst[module_idP].RA_tx_subframe = subframeP; - UE_mac_inst[module_idP].RA_backoff_frame = frameP; - UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; - // Fill in preamble and PRACH resource - get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,1,NULL); - generate_ulsch_header((uint8_t*)ulsch_buff, // mac header - 1, // num sdus - 0, // short pading - &Size16, // sdu length - &lcid, // sdu lcid - NULL, // power headroom - &UE_mac_inst[module_idP].crnti, // crnti - NULL, // truncated bsr - NULL, // short bsr - NULL, // long_bsr - 0); //post_padding - - return(&UE_mac_inst[module_idP].RA_prach_resources); - } - } else { // RACH is active - LOG_D(MAC,"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",module_idP, - frameP,subframeP,UE_mac_inst[module_idP].RA_window_cnt, - UE_mac_inst[module_idP].RA_tx_frame,UE_mac_inst[module_idP].RA_tx_subframe); - - // compute backoff parameters - if (UE_mac_inst[module_idP].RA_backoff_cnt>0) { - frame_diff = (sframe_t)frameP - UE_mac_inst[module_idP].RA_backoff_frame; - - if (frame_diff < 0) { - frame_diff = -frame_diff; - } - - UE_mac_inst[module_idP].RA_backoff_cnt -= ((10*frame_diff) + (subframeP-UE_mac_inst[module_idP].RA_backoff_subframe)); - - UE_mac_inst[module_idP].RA_backoff_frame = frameP; - UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; - } - - // compute RA window parameters - if (UE_mac_inst[module_idP].RA_window_cnt>0) { - frame_diff = (frame_t)frameP - UE_mac_inst[module_idP].RA_tx_frame; - - if (frame_diff < 0) { - frame_diff = -frame_diff; - } - - UE_mac_inst[module_idP].RA_window_cnt -= ((10*frame_diff) + (subframeP-UE_mac_inst[module_idP].RA_tx_subframe)); - LOG_D(MAC,"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, adjusted window cnt %d\n",module_idP, - frameP,subframeP,UE_mac_inst[module_idP].RA_window_cnt); - } - - if ((UE_mac_inst[module_idP].RA_window_cnt<=0) && - (UE_mac_inst[module_idP].RA_backoff_cnt<=0)) { - - UE_mac_inst[module_idP].RA_tx_frame = frameP; - UE_mac_inst[module_idP].RA_tx_subframe = subframeP; - UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER++; - UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER += - (rach_ConfigCommon->powerRampingParameters.powerRampingStep<<1); // 2dB increments in ASN.1 definition - int preambleTransMax = -1; - switch (rach_ConfigCommon->ra_SupervisionInfo.preambleTransMax) { - case PreambleTransMax_n3: - preambleTransMax = 3; - break; - case PreambleTransMax_n4: - preambleTransMax = 4; - break; - case PreambleTransMax_n5: - preambleTransMax = 5; - break; - case PreambleTransMax_n6: - preambleTransMax = 6; - break; - case PreambleTransMax_n7: - preambleTransMax = 7; - break; - case PreambleTransMax_n8: - preambleTransMax = 8; - break; - case PreambleTransMax_n10: - preambleTransMax = 10; - break; - case PreambleTransMax_n20: - preambleTransMax = 20; - break; - case PreambleTransMax_n50: - preambleTransMax = 50; - break; - case PreambleTransMax_n100: - preambleTransMax = 100; - break; - case PreambleTransMax_n200: - preambleTransMax = 200; - break; - } - - if (UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax) { - LOG_D(MAC,"[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n",module_idP,frameP,preambleTransMax); - // send message to RRC - UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER=1; - UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER = get_Po_NOMINAL_PUSCH(module_idP,CC_id); + + if (UE_mac_inst[module_idP].RA_active == 0) { + LOG_I(MAC, "RA not active\n"); + // check if RRC is ready to initiate the RA procedure + Size = mac_rrc_data_req(module_idP, + CC_id, + frameP, + CCCH, 1, + &UE_mac_inst[module_idP]. + CCCH_pdu.payload[sizeof + (SCH_SUBHEADER_SHORT) + + 1], 0, eNB_indexP, + 0); + Size16 = (uint16_t) Size; + + // LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size); + LOG_I(RRC, + "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_DATA_REQ (RRCConnectionRequest eNB %d) --->][MAC_UE][MOD %02d][]\n", + frameP, module_idP, eNB_indexP, module_idP); + LOG_I(MAC, + "[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", + module_idP, frameP, Size); + + if (Size > 0) { + + UE_mac_inst[module_idP].RA_active = 1; + UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = + 1; + UE_mac_inst[module_idP].RA_Msg3_size = + Size + sizeof(SCH_SUBHEADER_SHORT) + + sizeof(SCH_SUBHEADER_SHORT); + UE_mac_inst[module_idP].RA_prachMaskIndex = 0; + UE_mac_inst[module_idP].RA_prach_resources.Msg3 = + UE_mac_inst[module_idP].CCCH_pdu.payload; + UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) + + AssertFatal(rach_ConfigCommon != NULL, + "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n", + module_idP, frameP); + UE_mac_inst[module_idP].RA_window_cnt = + 2 + + rach_ConfigCommon->ra_SupervisionInfo. + ra_ResponseWindowSize; + + if (UE_mac_inst[module_idP].RA_window_cnt == 9) { + UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10! + } + + UE_mac_inst[module_idP].RA_tx_frame = frameP; + UE_mac_inst[module_idP].RA_tx_subframe = subframeP; + UE_mac_inst[module_idP].RA_backoff_frame = frameP; + UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; + // Fill in preamble and PRACH resource + get_prach_resources(module_idP, CC_id, eNB_indexP, + subframeP, 1, NULL); + + generate_ulsch_header((uint8_t *) & UE_mac_inst[module_idP].CCCH_pdu.payload[0], // mac header + 1, // num sdus + 0, // short pading + &Size16, // sdu length + &lcid, // sdu lcid + NULL, // power headroom + NULL, // crnti + NULL, // truncated bsr + NULL, // short bsr + NULL, // long_bsr + 1); //post_padding + return (&UE_mac_inst[module_idP].RA_prach_resources); + + } else if (UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID + [DCCH]] > 0) { + // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example) + dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element + rlc_status = + mac_rlc_status_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_indexP, frameP, subframeP, + ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6); + + if (UE_mac_inst[module_idP].crnti_before_ho) + LOG_D(MAC, + "[UE %d] Frame %d : UL-DCCH -> ULSCH, HO RRCConnectionReconfigurationComplete (%x, %x), RRC message has %d bytes to send throug PRACH (mac header len %d)\n", + module_idP, frameP, + UE_mac_inst[module_idP].crnti, + UE_mac_inst[module_idP].crnti_before_ho, + rlc_status.bytes_in_buffer, dcch_header_len); + else + LOG_D(MAC, + "[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to send through PRACH(mac header len %d)\n", + module_idP, frameP, rlc_status.bytes_in_buffer, + dcch_header_len); + + sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, //not used + (char *) &ulsch_buff[0]); + + LOG_D(MAC, "[UE %d] TX Got %d bytes for DCCH\n", + module_idP, sdu_lengths[0]); + update_bsr(module_idP, frameP, subframeP, eNB_indexP); + UE_mac_inst[module_idP]. + scheduling_info.BSR[UE_mac_inst[module_idP]. + scheduling_info.LCGID[DCCH]] = + locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, + UE_mac_inst + [module_idP].scheduling_info.BSR_bytes + [UE_mac_inst + [module_idP].scheduling_info.LCGID + [DCCH]]); + + //TO DO: fill BSR infos in UL TBS + + //header_len +=2; + UE_mac_inst[module_idP].RA_active = 1; + UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = + 1; + UE_mac_inst[module_idP].RA_Msg3_size = + Size + dcch_header_len; + UE_mac_inst[module_idP].RA_prachMaskIndex = 0; + UE_mac_inst[module_idP].RA_prach_resources.Msg3 = + ulsch_buff; + UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) + + AssertFatal(rach_ConfigCommon != NULL, + "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n", + module_idP, frameP); + UE_mac_inst[module_idP].RA_window_cnt = + 2 + + rach_ConfigCommon->ra_SupervisionInfo. + ra_ResponseWindowSize; + + if (UE_mac_inst[module_idP].RA_window_cnt == 9) { + UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10! + } + + + UE_mac_inst[module_idP].RA_tx_frame = frameP; + UE_mac_inst[module_idP].RA_tx_subframe = subframeP; + UE_mac_inst[module_idP].RA_backoff_frame = frameP; + UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; + // Fill in preamble and PRACH resource + get_prach_resources(module_idP, CC_id, eNB_indexP, + subframeP, 1, NULL); + generate_ulsch_header((uint8_t *) ulsch_buff, // mac header + 1, // num sdus + 0, // short pading + &Size16, // sdu length + &lcid, // sdu lcid + NULL, // power headroom + &UE_mac_inst[module_idP].crnti, // crnti + NULL, // truncated bsr + NULL, // short bsr + NULL, // long_bsr + 0); //post_padding + + return (&UE_mac_inst[module_idP].RA_prach_resources); + } + } else { // RACH is active + LOG_D(MAC, + "[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n", + module_idP, frameP, subframeP, + UE_mac_inst[module_idP].RA_window_cnt, + UE_mac_inst[module_idP].RA_tx_frame, + UE_mac_inst[module_idP].RA_tx_subframe); + + // compute backoff parameters + if (UE_mac_inst[module_idP].RA_backoff_cnt > 0) { + frame_diff = + (sframe_t) frameP - + UE_mac_inst[module_idP].RA_backoff_frame; + + if (frame_diff < 0) { + frame_diff = -frame_diff; + } + + UE_mac_inst[module_idP].RA_backoff_cnt -= + ((10 * frame_diff) + + (subframeP - + UE_mac_inst[module_idP].RA_backoff_subframe)); + + UE_mac_inst[module_idP].RA_backoff_frame = frameP; + UE_mac_inst[module_idP].RA_backoff_subframe = subframeP; + } + // compute RA window parameters + if (UE_mac_inst[module_idP].RA_window_cnt > 0) { + frame_diff = + (frame_t) frameP - UE_mac_inst[module_idP].RA_tx_frame; + + if (frame_diff < 0) { + frame_diff = -frame_diff; + } + + UE_mac_inst[module_idP].RA_window_cnt -= + ((10 * frame_diff) + + (subframeP - UE_mac_inst[module_idP].RA_tx_subframe)); + LOG_D(MAC, + "[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, adjusted window cnt %d\n", + module_idP, frameP, subframeP, + UE_mac_inst[module_idP].RA_window_cnt); + } + + if ((UE_mac_inst[module_idP].RA_window_cnt <= 0) && + (UE_mac_inst[module_idP].RA_backoff_cnt <= 0)) { + + UE_mac_inst[module_idP].RA_tx_frame = frameP; + UE_mac_inst[module_idP].RA_tx_subframe = subframeP; + UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER++; + UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER += (rach_ConfigCommon->powerRampingParameters.powerRampingStep << 1); // 2dB increments in ASN.1 definition + int preambleTransMax = -1; + switch (rach_ConfigCommon->ra_SupervisionInfo. + preambleTransMax) { + case PreambleTransMax_n3: + preambleTransMax = 3; + break; + case PreambleTransMax_n4: + preambleTransMax = 4; + break; + case PreambleTransMax_n5: + preambleTransMax = 5; + break; + case PreambleTransMax_n6: + preambleTransMax = 6; + break; + case PreambleTransMax_n7: + preambleTransMax = 7; + break; + case PreambleTransMax_n8: + preambleTransMax = 8; + break; + case PreambleTransMax_n10: + preambleTransMax = 10; + break; + case PreambleTransMax_n20: + preambleTransMax = 20; + break; + case PreambleTransMax_n50: + preambleTransMax = 50; + break; + case PreambleTransMax_n100: + preambleTransMax = 100; + break; + case PreambleTransMax_n200: + preambleTransMax = 200; + break; + } + + if (UE_mac_inst[module_idP]. + RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax) { + LOG_D(MAC, + "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", + module_idP, frameP, preambleTransMax); + // send message to RRC + UE_mac_inst[module_idP]. + RA_PREAMBLE_TRANSMISSION_COUNTER = 1; + UE_mac_inst[module_idP]. + RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER + = get_Po_NOMINAL_PUSCH(module_idP, CC_id); + } + + UE_mac_inst[module_idP].RA_window_cnt = + 2 + + rach_ConfigCommon->ra_SupervisionInfo. + ra_ResponseWindowSize; + UE_mac_inst[module_idP].RA_backoff_cnt = 0; + + // Fill in preamble and PRACH resource + get_prach_resources(module_idP, CC_id, eNB_indexP, + subframeP, 0, NULL); + return (&UE_mac_inst[module_idP].RA_prach_resources); + } } - - UE_mac_inst[module_idP].RA_window_cnt = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize; - UE_mac_inst[module_idP].RA_backoff_cnt = 0; - - // Fill in preamble and PRACH resource - get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,0,NULL); - return(&UE_mac_inst[module_idP].RA_prach_resources); - } + } else if (UE_mode == PUSCH) { + LOG_D(MAC, + "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", + module_idP); + AssertFatal(1 == 0, ""); } - } else if (UE_mode == PUSCH) { - LOG_D(MAC,"[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...",module_idP); - AssertFatal(1==0,""); - } - - return(NULL); + + return (NULL); } diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c index ad870b63879f4dd05bd3faea7d550f8b9ec3062c..8d9e5bb3e14d88664d06a3f621f25cb07c033188 100644 --- a/openair2/LAYER2/MAC/rar_tools.c +++ b/openair2/LAYER2/MAC/rar_tools.c @@ -40,269 +40,246 @@ #define DEBUG_RAR -extern unsigned int localRIV2alloc_LUT25[512]; -extern unsigned int distRIV2alloc_LUT25[512]; +extern unsigned int localRIV2alloc_LUT25[512]; +extern unsigned int distRIV2alloc_LUT25[512]; extern unsigned short RIV2nb_rb_LUT25[512]; extern unsigned short RIV2first_rb_LUT25[512]; extern RAN_CONTEXT_t RC; //------------------------------------------------------------------------------ -unsigned short fill_rar( - const module_id_t module_idP, - const int CC_id, - const frame_t frameP, - uint8_t* const dlsch_buffer, - const uint16_t N_RB_UL, - const uint8_t input_buffer_length -) +unsigned short +fill_rar(const module_id_t module_idP, + const int CC_id, + RA_t * ra, + const frame_t frameP, + uint8_t * const dlsch_buffer, + const uint16_t N_RB_UL, const uint8_t input_buffer_length) //------------------------------------------------------------------------------ { - RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; - // RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1); - uint8_t *rar = (uint8_t *)(dlsch_buffer+1); - int i,ra_idx = -1; - RA_TEMPLATE *RA_template; - - AssertFatal(CC_id < MAX_NUM_CCs, "CC_id %u < MAX_NUM_CCs %u", CC_id, MAX_NUM_CCs); - - for (i=0; i<NB_RA_PROC_MAX; i++) { - if (RC.mac[module_idP]->common_channels[CC_id].RA_template[i].generate_rar == 1) { - ra_idx=i; - RC.mac[module_idP]->common_channels[CC_id].RA_template[i].generate_rar = 0; - break; + RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer; + uint8_t *rar = (uint8_t *) (dlsch_buffer + 1); + + + // subheader fixed + rarh->E = 0; // First and last RAR + rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader + rarh->RAPID = ra->preamble_index; // Respond to Preamble 0 only for the moment + rar[4] = (uint8_t) (ra->rnti >> 8); + rar[5] = (uint8_t) (ra->rnti & 0xff); + //ra->timing_offset = 0; + ra->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps + rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4 + rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4 + ra->msg3_first_rb = 6; + ra->msg3_nb_rb = 1; + uint16_t rballoc = mac_computeRIV(N_RB_UL, ra->msg3_first_rb, ra->msg3_nb_rb); // first PRB only for UL Grant + rar[1] |= (rballoc >> 7) & 7; // Hopping = 0 (bit 3), 3 MSBs of rballoc + rar[2] = ((uint8_t) (rballoc & 0xff)) << 1; // 7 LSBs of rballoc + ra->msg3_mcs = 10; + ra->msg3_TPC = 3; + ra->msg3_ULdelay = 0; + ra->msg3_cqireq = 0; + rar[2] |= ((ra->msg3_mcs & 0x8) >> 3); // mcs 10 + rar[3] = + (((ra->msg3_mcs & 0x7) << 5)) | ((ra->msg3_TPC & 7) << 2) | + ((ra->msg3_ULdelay & 1) << 1) | (ra->msg3_cqireq & 1); + + if (opt_enabled) { + trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1, + RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe, + 0, 0); + LOG_D(OPT, + "[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n", + module_idP, CC_id, frameP, ra->rnti, rarh->RAPID, + input_buffer_length); } - } - RA_template = &RC.mac[module_idP]->common_channels[CC_id].RA_template[ra_idx]; - - //DevAssert( ra_idx != -1 ); - if (ra_idx==-1) - return(0); - - // subheader fixed - rarh->E = 0; // First and last RAR - rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader - rarh->RAPID = RA_template->preamble_index; // Respond to Preamble 0 only for the moment - rar[4] = (uint8_t)(RA_template->rnti>>8); - rar[5] = (uint8_t)(RA_template->rnti&0xff); - //RA_template->timing_offset = 0; - RA_template->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps - rar[0] = (uint8_t)(RA_template->timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4 - rar[1] = (uint8_t)(RA_template->timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4 - RA_template->msg3_first_rb=6; - RA_template->msg3_nb_rb=1; - uint16_t rballoc = mac_computeRIV(N_RB_UL,RA_template->msg3_first_rb,RA_template->msg3_nb_rb); // first PRB only for UL Grant - rar[1] |= (rballoc>>7)&7; // Hopping = 0 (bit 3), 3 MSBs of rballoc - rar[2] = ((uint8_t)(rballoc&0xff))<<1; // 7 LSBs of rballoc - RA_template->msg3_mcs = 10; - RA_template->msg3_TPC = 3; - RA_template->msg3_ULdelay = 0; - RA_template->msg3_cqireq = 0; - rar[2] |= ((RA_template->msg3_mcs&0x8)>>3); // mcs 10 - rar[3] = (((RA_template->msg3_mcs&0x7)<<5)) | ((RA_template->msg3_TPC&7)<<2) | ((RA_template->msg3_ULdelay&1)<<1) | (RA_template->msg3_cqireq&1); - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Generating RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ra_idx %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n", - module_idP, CC_id, - frameP, - *(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5], - ra_idx, - RA_template->rnti, - rarh->RAPID,RC.mac[module_idP]->common_channels[CC_id].RA_template[0].preamble_index, - RA_template->timing_offset); - - if (opt_enabled) { - trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1, - RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe, 0, 0); - LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n", - module_idP, CC_id, frameP, RA_template->rnti, - rarh->RAPID, input_buffer_length); - } - - return(RA_template->rnti); + + return (ra->rnti); } #ifdef Rel14 //------------------------------------------------------------------------------ -unsigned short fill_rar_br(eNB_MAC_INST *eNB, - int CC_id, - RA_TEMPLATE *RA_template, - const frame_t frameP, - const sub_frame_t subframeP, - uint8_t* const dlsch_buffer, - const uint8_t ce_level -) +unsigned short +fill_rar_br(eNB_MAC_INST * eNB, + int CC_id, + RA_t * ra, + const frame_t frameP, + const sub_frame_t subframeP, + uint8_t * const dlsch_buffer, const uint8_t ce_level) //------------------------------------------------------------------------------ { - RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - uint8_t *rar = (uint8_t *)(dlsch_buffer+1); - // uint8_t nb,reps; - uint8_t rballoc; - uint8_t mcs,TPC,ULdelay,cqireq; - int input_buffer_length; - - - AssertFatal(RA_template != NULL, "RA is null \n"); - - // subheader fixed - rarh->E = 0; // First and last RAR - rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader - rarh->RAPID = RA_template->preamble_index; // Respond to Preamble 0 only for the moment - RA_template->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps - rar[0] = (uint8_t)(RA_template->timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4 - rar[1] = (uint8_t)(RA_template->timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4 - - int N_NB_index; - - AssertFatal(1==0,"RAR for BL/CE Still to be finished ...\n"); - - // Copy the Msg2 narrowband - RA_template->msg34_narrowband = RA_template->msg2_narrowband; - - if (ce_level<2) { //CE Level 0,1, CEmodeA - input_buffer_length =6; - - N_NB_index = get_numnarrowbandbits(cc->mib->message.dl_Bandwidth); - - rar[4] = (uint8_t)(RA_template->rnti>>8); - rar[5] = (uint8_t)(RA_template->rnti&0xff); - //cc->RA_template[ra_idx].timing_offset = 0; - // nb = 0; - rballoc = mac_computeRIV(6,1+ce_level,1); // one PRB only for UL Grant in position 1+ce_level within Narrowband - rar[1] |= (rballoc&15)<<(4-N_NB_index); // Hopping = 0 (bit 3), 3 MSBs of rballoc - - // reps = 4; - mcs = 7; - TPC = 3; // no power increase - ULdelay = 0; - cqireq = 0; - rar[2] |= ((mcs&0x8)>>3); // mcs 10 - rar[3] = (((mcs&0x7)<<5)) | ((TPC&7)<<2) | ((ULdelay&1)<<1) | (cqireq&1); - } - else { // CE level 2,3 => CEModeB - - input_buffer_length =5; - - rar[3] = (uint8_t)(RA_template->rnti>>8); - rar[4] = (uint8_t)(RA_template->rnti&0xff); - } - LOG_D(MAC,"[RAPROC] Frame %d Generating RAR BR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ce_level %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n", - frameP, - *(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5], - ce_level, - RA_template->rnti, - rarh->RAPID,RA_template->preamble_index, - RA_template->timing_offset); - - if (opt_enabled) { - trace_pdu(1, dlsch_buffer, input_buffer_length, eNB->Mod_id, 2, 1, - eNB->frame, eNB->subframe, 0, 0); - LOG_D(OPT,"[RAPROC] RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n", - frameP, RA_template->rnti, - rarh->RAPID, input_buffer_length); - } - - return(RA_template->rnti); + RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer; + COMMON_channels_t *cc = &eNB->common_channels[CC_id]; + uint8_t *rar = (uint8_t *) (dlsch_buffer + 1); + // uint8_t nb,reps; + uint8_t rballoc; + uint8_t mcs, TPC, ULdelay, cqireq; + int input_buffer_length; + + + AssertFatal(ra != NULL, "RA is null \n"); + + // subheader fixed + rarh->E = 0; // First and last RAR + rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader + rarh->RAPID = ra->preamble_index; // Respond to Preamble 0 only for the moment + ra->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps + rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4 + rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4 + + int N_NB_index; + + AssertFatal(1 == 0, "RAR for BL/CE Still to be finished ...\n"); + + // Copy the Msg2 narrowband + ra->msg34_narrowband = ra->msg2_narrowband; + + if (ce_level < 2) { //CE Level 0,1, CEmodeA + input_buffer_length = 6; + + N_NB_index = get_numnarrowbandbits(cc->mib->message.dl_Bandwidth); + + rar[4] = (uint8_t) (ra->rnti >> 8); + rar[5] = (uint8_t) (ra->rnti & 0xff); + //cc->ra[ra_idx].timing_offset = 0; + // nb = 0; + rballoc = mac_computeRIV(6, 1 + ce_level, 1); // one PRB only for UL Grant in position 1+ce_level within Narrowband + rar[1] |= (rballoc & 15) << (4 - N_NB_index); // Hopping = 0 (bit 3), 3 MSBs of rballoc + + // reps = 4; + mcs = 7; + TPC = 3; // no power increase + ULdelay = 0; + cqireq = 0; + rar[2] |= ((mcs & 0x8) >> 3); // mcs 10 + rar[3] = + (((mcs & 0x7) << 5)) | ((TPC & 7) << 2) | ((ULdelay & 1) << 1) + | (cqireq & 1); + } else { // CE level 2,3 => CEModeB + + input_buffer_length = 5; + + rar[3] = (uint8_t) (ra->rnti >> 8); + rar[4] = (uint8_t) (ra->rnti & 0xff); + } + LOG_D(MAC, + "[RAPROC] Frame %d Generating RAR BR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ce_level %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n", + frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], + rar[4], rar[5], ce_level, ra->rnti, rarh->RAPID, + ra->preamble_index, ra->timing_offset); + + if (opt_enabled) { + trace_pdu(1, dlsch_buffer, input_buffer_length, eNB->Mod_id, 2, 1, + eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT, + "[RAPROC] RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n", + frameP, ra->rnti, rarh->RAPID, input_buffer_length); + } + + return (ra->rnti); } #endif //------------------------------------------------------------------------------ -uint16_t -ue_process_rar( - const module_id_t module_idP, - const int CC_id, - const frame_t frameP, - const rnti_t ra_rnti, - uint8_t* const dlsch_buffer, - rnti_t* const t_crnti, - const uint8_t preamble_index, - uint8_t* selected_rar_buffer // output argument for storing the selected RAR header and RAR payload -) +uint16_t ue_process_rar(const module_id_t module_idP, const int CC_id, const frame_t frameP, const rnti_t ra_rnti, uint8_t * const dlsch_buffer, rnti_t * const t_crnti, const uint8_t preamble_index, uint8_t * selected_rar_buffer // output argument for storing the selected RAR header and RAR payload + ) //------------------------------------------------------------------------------ { - uint16_t ret = 0; // return value - - RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; - // RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1); - uint8_t *rar = (uint8_t *)(dlsch_buffer+1); - - // get the last RAR payload for working with CMW500 - uint8_t n_rarpy = 0; // number of RAR payloads - uint8_t n_rarh = 0; // number of MAC RAR subheaders - uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs - while (1) { - n_rarh++; - if (rarh->T == 1) { - n_rarpy++; - LOG_D(MAC, "RAPID %d\n", rarh->RAPID); - } - - if (rarh->RAPID == preamble_index) { - LOG_D(PHY, "Found RAR with the intended RAPID %d\n", rarh->RAPID); - rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6); - break; - } - - if (abs((int)rarh->RAPID - (int)preamble_index) < abs((int)best_rx_rapid - (int)preamble_index)) { - best_rx_rapid = rarh->RAPID; - rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6); - } - - if (rarh->E == 0) { - LOG_I(PHY, "No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n", best_rx_rapid); - break; - } else { - rarh++; - } - }; - LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", n_rarh, n_rarpy); - - if (CC_id>0) { - LOG_W(MAC,"Should not have received RAR on secondary CCs! \n"); - return(0xffff); - } - - LOG_I(MAC,"[eNB %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",module_idP,frameP, - *(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5], - rarh->RAPID,preamble_index); + uint16_t ret = 0; // return value + + RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer; + // RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1); + uint8_t *rar = (uint8_t *) (dlsch_buffer + 1); + + // get the last RAR payload for working with CMW500 + uint8_t n_rarpy = 0; // number of RAR payloads + uint8_t n_rarh = 0; // number of MAC RAR subheaders + uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs + while (1) { + n_rarh++; + if (rarh->T == 1) { + n_rarpy++; + LOG_D(MAC, "RAPID %d\n", rarh->RAPID); + } + + if (rarh->RAPID == preamble_index) { + LOG_D(PHY, "Found RAR with the intended RAPID %d\n", + rarh->RAPID); + rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6); + break; + } + + if (abs((int) rarh->RAPID - (int) preamble_index) < + abs((int) best_rx_rapid - (int) preamble_index)) { + best_rx_rapid = rarh->RAPID; + rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6); + } + + if (rarh->E == 0) { + LOG_I(PHY, + "No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n", + best_rx_rapid); + break; + } else { + rarh++; + } + }; + LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", + n_rarh, n_rarpy); + + if (CC_id > 0) { + LOG_W(MAC, "Should not have received RAR on secondary CCs! \n"); + return (0xffff); + } + + LOG_I(MAC, + "[eNB %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", + module_idP, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], + rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); #ifdef DEBUG_RAR - LOG_D(MAC,"[UE %d][RAPROC] rarh->E %d\n",module_idP,rarh->E); - LOG_D(MAC,"[UE %d][RAPROC] rarh->T %d\n",module_idP,rarh->T); - LOG_D(MAC,"[UE %d][RAPROC] rarh->RAPID %d\n",module_idP,rarh->RAPID); - - // LOG_I(MAC,"[UE %d][RAPROC] rar->R %d\n",module_idP,rar->R); - LOG_D(MAC,"[UE %d][RAPROC] rar->Timing_Advance_Command %d\n",module_idP,(((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); - // LOG_I(MAC,"[UE %d][RAPROC] rar->hopping_flag %d\n",module_idP,rar->hopping_flag); - // LOG_I(MAC,"[UE %d][RAPROC] rar->rb_alloc %d\n",module_idP,rar->rb_alloc); - // LOG_I(MAC,"[UE %d][RAPROC] rar->mcs %d\n",module_idP,rar->mcs); - // LOG_I(MAC,"[UE %d][RAPROC] rar->TPC %d\n",module_idP,rar->TPC); - // LOG_I(MAC,"[UE %d][RAPROC] rar->UL_delay %d\n",module_idP,rar->UL_delay); - // LOG_I(MAC,"[UE %d][RAPROC] rar->cqi_req %d\n",module_idP,rar->cqi_req); - LOG_D(MAC,"[UE %d][RAPROC] rar->t_crnti %x\n",module_idP,(uint16_t)rar[5]+(rar[4]<<8)); + LOG_D(MAC, "[UE %d][RAPROC] rarh->E %d\n", module_idP, rarh->E); + LOG_D(MAC, "[UE %d][RAPROC] rarh->T %d\n", module_idP, rarh->T); + LOG_D(MAC, "[UE %d][RAPROC] rarh->RAPID %d\n", module_idP, + rarh->RAPID); + + // LOG_I(MAC,"[UE %d][RAPROC] rar->R %d\n",module_idP,rar->R); + LOG_D(MAC, "[UE %d][RAPROC] rar->Timing_Advance_Command %d\n", + module_idP, (((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4)); + // LOG_I(MAC,"[UE %d][RAPROC] rar->hopping_flag %d\n",module_idP,rar->hopping_flag); + // LOG_I(MAC,"[UE %d][RAPROC] rar->rb_alloc %d\n",module_idP,rar->rb_alloc); + // LOG_I(MAC,"[UE %d][RAPROC] rar->mcs %d\n",module_idP,rar->mcs); + // LOG_I(MAC,"[UE %d][RAPROC] rar->TPC %d\n",module_idP,rar->TPC); + // LOG_I(MAC,"[UE %d][RAPROC] rar->UL_delay %d\n",module_idP,rar->UL_delay); + // LOG_I(MAC,"[UE %d][RAPROC] rar->cqi_req %d\n",module_idP,rar->cqi_req); + LOG_D(MAC, "[UE %d][RAPROC] rar->t_crnti %x\n", module_idP, + (uint16_t) rar[5] + (rar[4] << 8)); #endif - if (opt_enabled) { - LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n", - module_idP, CC_id, frameP, ra_rnti); - trace_pdu(1, (uint8_t*)dlsch_buffer, n_rarh + n_rarpy*6, module_idP, 2, ra_rnti, - UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0); - } - - if (preamble_index == rarh->RAPID) { - *t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti; - UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti; - //return(rar->Timing_Advance_Command); - ret = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); - } else { - UE_mac_inst[module_idP].crnti=0; - ret = (0xffff); - } - - // move the selected RAR to the front of the RA_PDSCH buffer - memcpy(selected_rar_buffer+0, (uint8_t*)rarh, 1); - memcpy(selected_rar_buffer+1, (uint8_t*)rar , 6); - - return ret; + if (opt_enabled) { + LOG_D(OPT, + "[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n", + module_idP, CC_id, frameP, ra_rnti); + trace_pdu(1, (uint8_t *) dlsch_buffer, n_rarh + n_rarpy * 6, + module_idP, 2, ra_rnti, UE_mac_inst[module_idP].rxFrame, + UE_mac_inst[module_idP].rxSubframe, 0, 0); + } + + if (preamble_index == rarh->RAPID) { + *t_crnti = (uint16_t) rar[5] + (rar[4] << 8); //rar->t_crnti; + UE_mac_inst[module_idP].crnti = *t_crnti; //rar->t_crnti; + //return(rar->Timing_Advance_Command); + ret = ((((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4)); + } else { + UE_mac_inst[module_idP].crnti = 0; + ret = (0xffff); + } + + // move the selected RAR to the front of the RA_PDSCH buffer + memcpy(selected_rar_buffer + 0, (uint8_t *) rarh, 1); + memcpy(selected_rar_buffer + 1, (uint8_t *) rar, 6); + + return ret; } diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index d6c2512309ebf1130a79dc04dca51d111cb14e89..5b73a76312804f1a34536227101c90bda01a0ca8 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -37,10 +37,10 @@ #include "defs.h" #include "proto.h" #ifdef PHY_EMUL -# include "SIMULATION/PHY_EMULATION/impl_defs.h" +#include "SIMULATION/PHY_EMULATION/impl_defs.h" #else -# include "SCHED/defs.h" -# include "PHY/impl_defs_top.h" +#include "SCHED/defs.h" +#include "PHY/impl_defs_top.h" #endif #include "PHY_INTERFACE/extern.h" #include "COMMON/mac_rrc_primitives.h" @@ -54,17 +54,17 @@ #include "OCG_extern.h" #ifdef PHY_EMUL -# include "SIMULATION/simulation_defs.h" +#include "SIMULATION/simulation_defs.h" #endif #include "pdcp.h" #if defined(ENABLE_ITTI) -# include "intertask_interface.h" +#include "intertask_interface.h" #endif #include "assertions.h" -#include "SIMULATION/TOOLS/defs.h" // for taus +#include "SIMULATION/TOOLS/defs.h" // for taus #define DEBUG_HEADER_PARSING 1 #define ENABLE_MAC_PAYLOAD_DEBUG 1 @@ -77,1738 +77,2071 @@ extern uint8_t usim_test; #endif */ mapping BSR_names[] = { - {"NONE", 0}, - {"SHORT BSR", 1}, - {"TRUNCATED BSR", 2}, - {"LONG BSR", 3}, - {"PADDING BSR", 4}, - {NULL, -1} + {"NONE", 0}, + {"SHORT BSR", 1}, + {"TRUNCATED BSR", 2}, + {"LONG BSR", 3}, + {"PADDING BSR", 4}, + {NULL, -1} }; void ue_init_mac(module_id_t module_idP) { - int i; - // default values as deined in 36.331 sec 9.2.2 - LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP); - //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL; - UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= RetxBSR_Timer_r12_sf10240; - UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=PeriodicBSR_Timer_r12_infinity; - UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; - UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; - UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; - UE_mac_inst[module_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup; - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0; - UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer=0; - UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0; - UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; - UE_mac_inst[module_idP].scheduling_info.ttiBundling=0; - UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10=0; - UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10=0; - UE_mac_inst[module_idP].scheduling_info.drx_config=NULL; - UE_mac_inst[module_idP].scheduling_info.phr_config=NULL; - // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW. - UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; - UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; - UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; - - UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF = get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer); - UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF = get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer); - UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange); - UE_mac_inst[module_idP].PHR_reporting_active = 0; - - for (i=0; i < MAX_NUM_LCID; i++) { - LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i); - UE_mac_inst[module_idP].scheduling_info.Bj[i]=-1; - UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1; - - if (i < DTCH) { // initilize all control channels lcgid to 0 - UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0; - } else { // initialize all the data channels lcgid to 1 - UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1; - } - - UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=LCID_EMPTY; - UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0; - } + int i; + // default values as deined in 36.331 sec 9.2.2 + LOG_I(MAC, "[UE%d] Applying default macMainConfig\n", module_idP); + //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL; + UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer = + RetxBSR_Timer_r12_sf10240; + UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer = + PeriodicBSR_Timer_r12_infinity; + UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = + MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; + UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = + MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; + UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = + MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; + UE_mac_inst[module_idP].PHR_state = + MAC_MainConfig__phr_Config_PR_setup; + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER = 0; + UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer = 0; + UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running = 0; + UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx = + MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; + UE_mac_inst[module_idP].scheduling_info.ttiBundling = 0; + UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10 = 0; + UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10 = 0; + UE_mac_inst[module_idP].scheduling_info.drx_config = NULL; + UE_mac_inst[module_idP].scheduling_info.phr_config = NULL; + // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW. + UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; + + UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF = + get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP]. + scheduling_info.periodicPHR_Timer); + UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF = + get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP]. + scheduling_info.prohibitPHR_Timer); + UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = + get_db_dl_PathlossChange(UE_mac_inst[module_idP]. + scheduling_info.PathlossChange); + UE_mac_inst[module_idP].PHR_reporting_active = 0; + + for (i = 0; i < MAX_NUM_LCID; i++) { + LOG_D(MAC, + "[UE%d] Applying default logical channel config for LCGID %d\n", + module_idP, i); + UE_mac_inst[module_idP].scheduling_info.Bj[i] = -1; + UE_mac_inst[module_idP].scheduling_info.bucket_size[i] = -1; + + if (i < DTCH) { // initilize all control channels lcgid to 0 + UE_mac_inst[module_idP].scheduling_info.LCGID[i] = 0; + } else { // initialize all the data channels lcgid to 1 + UE_mac_inst[module_idP].scheduling_info.LCGID[i] = 1; + } + + UE_mac_inst[module_idP].scheduling_info.LCID_status[i] = + LCID_EMPTY; + UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0; + } #ifdef CBA - for (i=0; i <NUM_MAX_CBA_GROUP; i++) { - UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30)); - } + for (i = 0; i < NUM_MAX_CBA_GROUP; i++) { + UE_mac_inst[module_idP].cba_last_access[i] = + round(uniform_rngen(1, 30)); + } #endif } unsigned char *parse_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 *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_cont_res = 0,num_padding = 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) { - // printf("E=0\n"); - not_done = 0; - } - - lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID; - - if (lcid < UE_CONT_RES) { - //printf("[MAC][UE] header %x.%x.%x\n",mac_header_ptr[0],mac_header_ptr[1],mac_header_ptr[2]); - 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_LONG *)mac_header_ptr)->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; + unsigned char not_done = 1, num_ces = 0, num_cont_res = + 0, num_padding = 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) { + // printf("E=0\n"); + not_done = 0; + } + + lcid = ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->LCID; + + if (lcid < UE_CONT_RES) { + //printf("[MAC][UE] header %x.%x.%x\n",mac_header_ptr[0],mac_header_ptr[1],mac_header_ptr[2]); + 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_LONG *) mac_header_ptr)->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; #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] parse long sdu, size %x \n",length); + LOG_D(MAC, "[UE] parse long sdu, size %x \n", length); #endif - } else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) { - length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L; - mac_header_ptr += 2; - } - } + } else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) { + length = ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L; + mac_header_ptr += 2; + } + } #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %ld)\n", - num_sdus,lcid,length,mac_header_ptr-mac_header); + LOG_D(MAC, "[UE] sdu %d lcid %d length %d (offset now %ld)\n", + num_sdus, lcid, length, mac_header_ptr - mac_header); #endif - rx_lcids[num_sdus] = lcid; - rx_lengths[num_sdus] = length; - num_sdus++; - } else { // This is a control element subheader - if (lcid == SHORT_PADDING) { - num_padding ++; - mac_header_ptr++; - } else { - rx_ces[num_ces] = lcid; - num_ces++; - mac_header_ptr ++; - - if (lcid==TIMING_ADV_CMD) { - ce_len++; - } else if (lcid==UE_CONT_RES) { - - // FNA: check MAC Header is one of thoses defined in Annex B of 36.321 - // Check there is only 1 Contention Resolution - if (num_cont_res) { - LOG_W(MAC,"[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n"); - // exit parsing - return NULL; - - } - - // UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader - if ((not_done == 0) && ((num_sdus) || (num_ces > 1) || (num_padding))) { - LOG_W(MAC,"[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n",num_ces,num_sdus,num_padding); - // exit parsing - return NULL; - } - num_cont_res ++; - ce_len+=6; - } - } + rx_lcids[num_sdus] = lcid; + rx_lengths[num_sdus] = length; + num_sdus++; + } else { // This is a control element subheader + if (lcid == SHORT_PADDING) { + num_padding++; + mac_header_ptr++; + } else { + rx_ces[num_ces] = lcid; + num_ces++; + mac_header_ptr++; + + if (lcid == TIMING_ADV_CMD) { + ce_len++; + } else if (lcid == UE_CONT_RES) { + + // FNA: check MAC Header is one of thoses defined in Annex B of 36.321 + // Check there is only 1 Contention Resolution + if (num_cont_res) { + LOG_W(MAC, + "[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n"); + // exit parsing + return NULL; + + } + // UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader + if ((not_done == 0) + && ((num_sdus) || (num_ces > 1) || (num_padding))) { + LOG_W(MAC, + "[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n", + num_ces, num_sdus, num_padding); + // exit parsing + return NULL; + } + num_cont_res++; + ce_len += 6; + } + } #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] ce %d lcid %d (offset now %ld)\n",num_ces,lcid,mac_header_ptr-mac_header); + LOG_D(MAC, "[UE] ce %d lcid %d (offset now %ld)\n", num_ces, + lcid, mac_header_ptr - mac_header); #endif + } } - } - *num_ce = num_ces; - *num_sdu = num_sdus; + *num_ce = num_ces; + *num_sdu = num_sdus; - return(mac_header_ptr); + return (mac_header_ptr); } -uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_id,uint16_t rnti, sub_frame_t subframe) +uint32_t +ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, + uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe) { - // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti - // int MGL=6;// measurement gap length in ms - int MGRP = 0; // measurement gap repetition period in ms - int gapOffset = -1; - int T = 0; - - DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0); - - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - - // determin the measurement gap - if (UE_mac_inst[module_idP].measGapConfig !=NULL) { - if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) { - MGRP= 40; - gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp0; - } else if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) { - MGRP= 80; - gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp1; - } else { - LOG_W(MAC, "Measurement GAP offset is unknown\n"); + // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti + // int MGL=6;// measurement gap length in ms + int MGRP = 0; // measurement gap repetition period in ms + int gapOffset = -1; + int T = 0; + + DevCheck(module_idP < (int) NB_UE_INST, module_idP, NB_UE_INST, 0); + + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + + // determin the measurement gap + if (UE_mac_inst[module_idP].measGapConfig != NULL) { + if (UE_mac_inst[module_idP].measGapConfig->choice.setup. + gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) { + MGRP = 40; + gapOffset = + UE_mac_inst[module_idP].measGapConfig->choice. + setup.gapOffset.choice.gp0; + } else if (UE_mac_inst[module_idP].measGapConfig->choice. + setup.gapOffset.present == + MeasGapConfig__setup__gapOffset_PR_gp1) { + MGRP = 80; + gapOffset = + UE_mac_inst[module_idP].measGapConfig->choice. + setup.gapOffset.choice.gp1; + } else { + LOG_W(MAC, "Measurement GAP offset is unknown\n"); + } + + T = MGRP / 10; + DevAssert(T != 0); + + //check the measurement gap and sr prohibit timer + if ((subframe == gapOffset % 10) + && ((frameP % T) == (floor(gapOffset / 10))) + && (UE_mac_inst[module_idP]. + scheduling_info.sr_ProhibitTimer_Running == 0)) { + UE_mac_inst[module_idP].scheduling_info.SR_pending = 1; + return (0); + } } - T=MGRP/10; - DevAssert( T != 0 ); - - //check the measurement gap and sr prohibit timer - if ((subframe == gapOffset %10) && ((frameP %T) == (floor(gapOffset/10))) - && (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running ==0)) { - UE_mac_inst[module_idP].scheduling_info.SR_pending=1; - return(0); - } - } - - if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) && - (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) && - (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER < - (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax))) - ) { - LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", - module_idP,rnti,frameP,subframe, - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER, - (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)), - UE_mac_inst[module_idP].scheduling_info.SR_pending); - - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++; - - // start the sr-prohibittimer : rel 9 and above - if (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer > 0) { // timer configured - UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer--; - UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=1; + if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) && + (UE_mac_inst[module_idP].scheduling_info.SR_pending == 1) && + (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER < + (1 << + (2 + + UE_mac_inst[module_idP]. + physicalConfigDedicated->schedulingRequestConfig->choice.setup. + dsr_TransMax)))) { + LOG_D(MAC, + "[UE %d][SR %x] Frame %d subframe %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", + module_idP, rnti, frameP, subframe, + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER, + (1 << + (2 + + UE_mac_inst[module_idP]. + physicalConfigDedicated->schedulingRequestConfig->choice. + setup.dsr_TransMax)), + UE_mac_inst[module_idP].scheduling_info.SR_pending); + + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++; + + // start the sr-prohibittimer : rel 9 and above + if (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer > 0) { // timer configured + UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer--; + UE_mac_inst[module_idP].scheduling_info. + sr_ProhibitTimer_Running = 1; + } else { + UE_mac_inst[module_idP].scheduling_info. + sr_ProhibitTimer_Running = 0; + } + + LOG_D(MAC, + "[UE %d][SR %x] Frame %d subframe %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", + module_idP, rnti, frameP, subframe, + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER, + (1 << + (2 + + UE_mac_inst[module_idP]. + physicalConfigDedicated->schedulingRequestConfig->choice. + setup.dsr_TransMax)), + UE_mac_inst[module_idP].scheduling_info.SR_pending); + + //UE_mac_inst[module_idP].ul_active =1; + return (1); //instruct phy to signal SR } else { - UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0; - } - - LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", - module_idP,rnti,frameP,subframe, - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER, - (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)), - UE_mac_inst[module_idP].scheduling_info.SR_pending); - - //UE_mac_inst[module_idP].ul_active =1; - return(1); //instruct phy to signal SR - } else { - // notify RRC to relase PUCCH/SRS - // clear any configured dl/ul - // initiate RA - if (UE_mac_inst[module_idP].scheduling_info.SR_pending){ - // release all pucch resource - UE_mac_inst[module_idP].physicalConfigDedicated = NULL; - UE_mac_inst[module_idP].ul_active=0; - UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE; - - LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP); - } - UE_mac_inst[module_idP].scheduling_info.SR_pending=0; - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0; - return(0); - } + // notify RRC to relase PUCCH/SRS + // clear any configured dl/ul + // initiate RA + if (UE_mac_inst[module_idP].scheduling_info.SR_pending) { + // release all pucch resource + UE_mac_inst[module_idP].physicalConfigDedicated = NULL; + UE_mac_inst[module_idP].ul_active = 0; + UE_mac_inst[module_idP].BSR_reporting_active = + BSR_TRIGGER_NONE; + + LOG_I(MAC, "[UE %d] Release all SRs \n", module_idP); + } + UE_mac_inst[module_idP].scheduling_info.SR_pending = 0; + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER = 0; + return (0); + } } //------------------------------------------------------------------------------ void -ue_send_sdu( - module_id_t module_idP, +ue_send_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, - sub_frame_t subframeP, - uint8_t* sdu, - uint16_t sdu_len, - uint8_t eNB_index -) + sub_frame_t subframeP, + uint8_t * sdu, uint16_t sdu_len, uint8_t eNB_index) //------------------------------------------------------------------------------ { - 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 *tx_sdu; + 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 *tx_sdu; #if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); + start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); - LOG_T(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]); + LOG_T(MAC, "sdu: %x.%x.%x\n", sdu[0], sdu[1], sdu[2]); - if (opt_enabled) { - trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti, - frameP, subframeP, 0, 0); - LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n", - module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len); - } + if (opt_enabled) { + trace_pdu(1, sdu, sdu_len, module_idP, 3, + UE_mac_inst[module_idP].crnti, frameP, subframeP, 0, 0); + LOG_D(OPT, + "[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n", + module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len); + } - payload_ptr = parse_header(sdu,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_len); + payload_ptr = + parse_header(sdu, &num_ce, &num_sdu, rx_ces, rx_lcids, rx_lengths, + sdu_len); #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP, - frameP,eNB_index,num_ce,num_sdu); + LOG_D(MAC, + "[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n", + module_idP, frameP, eNB_index, num_ce, num_sdu); #endif #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC,"[UE %d] First 32 bytes of DLSCH : \n", module_idP); + LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); - for (i=0; i<32; i++) { - LOG_T(MAC,"%x.",sdu[i]); - } + for (i = 0; i < 32; i++) { + LOG_T(MAC, "%x.", sdu[i]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - if (payload_ptr != NULL) { - - for (i=0; i<num_ce; i++) { - // printf("ce %d : %d\n",i,rx_ces[i]); - switch (rx_ces[i]) { - case UE_CONT_RES: - - LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", - module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]); - - if (UE_mac_inst[module_idP].RA_active == 1) { - LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP); - UE_mac_inst[module_idP].RA_active=0; - // check if RA procedure has finished completely (no contention) - tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3]; - - //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits) - // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT) - for (i=0; i<6; i++) - if (tx_sdu[i] != payload_ptr[i]) { - LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP); - ra_failed(module_idP,CC_id,eNB_index); - UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); - return; - } - - LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n", module_idP, frameP); - UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0; - ra_succeeded(module_idP,CC_id,eNB_index); - } - - payload_ptr+=6; - break; - - case TIMING_ADV_CMD: + if (payload_ptr != NULL) { + + for (i = 0; i < num_ce; i++) { + // printf("ce %d : %d\n",i,rx_ces[i]); + switch (rx_ces[i]) { + case UE_CONT_RES: + + LOG_I(MAC, + "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", + module_idP, frameP, payload_ptr[0], payload_ptr[1], + payload_ptr[2], payload_ptr[3], payload_ptr[4], + payload_ptr[5]); + + if (UE_mac_inst[module_idP].RA_active == 1) { + LOG_I(MAC, + "[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", + module_idP, frameP); + UE_mac_inst[module_idP].RA_active = 0; + // check if RA procedure has finished completely (no contention) + tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3]; + + //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits) + // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT) + for (i = 0; i < 6; i++) + if (tx_sdu[i] != payload_ptr[i]) { + LOG_E(MAC, + "[UE %d][RAPROC] Contention detected, RA failed\n", + module_idP); + ra_failed(module_idP, CC_id, eNB_index); + UE_mac_inst + [module_idP]. + RA_contention_resolution_timer_active = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, + VCD_FUNCTION_OUT); + return; + } + + LOG_I(MAC, + "[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n", + module_idP, frameP); + UE_mac_inst + [module_idP]. + RA_contention_resolution_timer_active = 0; + ra_succeeded(module_idP, CC_id, eNB_index); + } + + payload_ptr += 6; + break; + + case TIMING_ADV_CMD: #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]); + LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, + payload_ptr[0]); #endif - process_timing_advance(module_idP,CC_id,payload_ptr[0]); - payload_ptr++; - break; + process_timing_advance(module_idP, CC_id, payload_ptr[0]); + payload_ptr++; + break; - case DRX_CMD: + case DRX_CMD: #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] CE %d : UE DRX :",i); + LOG_D(MAC, "[UE] CE %d : UE DRX :", i); #endif - payload_ptr++; - break; - } - } + payload_ptr++; + break; + } + } - for (i=0; i<num_sdu; i++) { + for (i = 0; i < num_sdu; i++) { #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]); + LOG_D(MAC, "[UE] SDU %d : LCID %d, length %d\n", i, + rx_lcids[i], rx_lengths[i]); #endif - - if (rx_lcids[i] == CCCH) { - LOG_D(MAC,"[UE %d] rnti %x Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n", - module_idP, - UE_mac_inst[module_idP].crnti, - frameP, - eNB_index, - rx_lengths[i]); + if (rx_lcids[i] == CCCH) { + + LOG_D(MAC, + "[UE %d] rnti %x Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n", + module_idP, UE_mac_inst[module_idP].crnti, frameP, + eNB_index, rx_lengths[i]); #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - int j; + int j; - for (j=0; j<rx_lengths[i]; j++) { - LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]); - } + for (j = 0; j < rx_lengths[i]; j++) { + LOG_T(MAC, "%x.", (uint8_t) payload_ptr[j]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - mac_rrc_data_ind(module_idP, - CC_id, - frameP,subframeP, - UE_mac_inst[module_idP].crnti, - CCCH, - (uint8_t*)payload_ptr, - rx_lengths[i], - ENB_FLAG_NO, - eNB_index, - 0); - - } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) { - LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i],eNB_index,rx_lengths[i]); - mac_rlc_data_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL); - - } else if ((rx_lcids[i] < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) { - - LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]); + mac_rrc_data_ind(module_idP, + CC_id, + frameP, subframeP, + UE_mac_inst[module_idP].crnti, + CCCH, + (uint8_t *) payload_ptr, + rx_lengths[i], ENB_FLAG_NO, eNB_index, 0); + + } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) { + LOG_D(MAC, + "[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", + module_idP, frameP, rx_lcids[i], eNB_index, + rx_lengths[i]); + mac_rlc_data_ind(module_idP, UE_mac_inst[module_idP].crnti, + eNB_index, frameP, ENB_FLAG_NO, + MBMS_FLAG_NO, rx_lcids[i], + (char *) payload_ptr, rx_lengths[i], 1, + NULL); + + } else if ((rx_lcids[i] < NB_RB_MAX) && (rx_lcids[i] > DCCH1)) { + + LOG_D(MAC, + "[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", + module_idP, frameP, rx_lcids[i], eNB_index, + rx_lengths[i]); #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - int j; - for (j=0;j<rx_lengths[i];j++) - LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]); - LOG_T(MAC,"\n"); + int j; + for (j = 0; j < rx_lengths[i]; j++) + LOG_T(MAC, "%x.", (unsigned char) payload_ptr[j]); + LOG_T(MAC, "\n"); #endif - mac_rlc_data_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL); - } else { - LOG_E(MAC,"[UE %d] Frame %d : unknown LCID %d (eNB %d)\n", module_idP, frameP,rx_lcids[i], eNB_index); - } - payload_ptr+= rx_lengths[i]; - } - } // end if (payload_ptr != NULL) - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); + mac_rlc_data_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + rx_lcids[i], + (char *) payload_ptr, rx_lengths[i], 1, + NULL); + } else { + LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (eNB %d)\n", + module_idP, frameP, rx_lcids[i], eNB_index); + } + payload_ptr += rx_lengths[i]; + } + } // end if (payload_ptr != NULL) + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); + stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); #endif } -void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len) +void +ue_decode_si(module_id_t module_idP, int CC_id, frame_t frameP, + uint8_t eNB_index, void *pdu, uint16_t len) { #if UE_TIMING_TRACE start_meas(&UE_mac_inst[module_idP].rx_si); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN); - - LOG_D(MAC,"[UE %d] Frame %d Sending SI to RRC (LCID Id %d,len %d)\n",module_idP,frameP,BCCH,len); - - mac_rrc_data_ind(module_idP, - CC_id, - frameP,0, // unknown subframe - SI_RNTI, - BCCH, - (uint8_t *)pdu, - len, - ENB_FLAG_NO, - eNB_index, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN); + + LOG_D(MAC, "[UE %d] Frame %d Sending SI to RRC (LCID Id %d,len %d)\n", + module_idP, frameP, BCCH, len); + + mac_rrc_data_ind(module_idP, CC_id, frameP, 0, // unknown subframe + SI_RNTI, + BCCH, (uint8_t *) pdu, len, ENB_FLAG_NO, eNB_index, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].rx_si); + stop_meas(&UE_mac_inst[module_idP].rx_si); #endif - if (opt_enabled == 1) { - trace_pdu(0, - (uint8_t *)pdu, - len, - module_idP, - 4, - 0xffff, - UE_mac_inst[module_idP].rxFrame, - UE_mac_inst[module_idP].rxSubframe, - 0, - 0); - LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", - module_idP, frameP, CC_id, 0xffff, len); - } + if (opt_enabled == 1) { + trace_pdu(0, + (uint8_t *) pdu, + len, + module_idP, + 4, + 0xffff, + UE_mac_inst[module_idP].rxFrame, + UE_mac_inst[module_idP].rxSubframe, 0, 0); + LOG_D(OPT, + "[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, len); + } } -void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len) +void +ue_decode_p(module_id_t module_idP, int CC_id, frame_t frameP, + uint8_t eNB_index, void *pdu, uint16_t len) { #if UE_TIMING_TRACE start_meas(&UE_mac_inst[module_idP].rx_p); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN); - - LOG_D(MAC,"[UE %d] Frame %d Sending Paging message to RRC (LCID Id %d,len %d)\n",module_idP,frameP,PCCH,len); - - mac_rrc_data_ind(module_idP, - CC_id, - frameP,0, // unknown subframe - P_RNTI, - PCCH, - (uint8_t *)pdu, - len, - ENB_FLAG_NO, - eNB_index, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN); + + LOG_D(MAC, + "[UE %d] Frame %d Sending Paging message to RRC (LCID Id %d,len %d)\n", + module_idP, frameP, PCCH, len); + + mac_rrc_data_ind(module_idP, CC_id, frameP, 0, // unknown subframe + P_RNTI, + PCCH, (uint8_t *) pdu, len, ENB_FLAG_NO, eNB_index, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].rx_p); + stop_meas(&UE_mac_inst[module_idP].rx_p); #endif - if (opt_enabled == 1) { - trace_pdu(0, - (uint8_t *)pdu, - len, - module_idP, - 4, - P_RNTI, - UE_mac_inst[module_idP].rxFrame, - UE_mac_inst[module_idP].rxSubframe, - 0, - 0); - LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", - module_idP, frameP, CC_id, P_RNTI, len); - } + if (opt_enabled == 1) { + trace_pdu(0, + (uint8_t *) pdu, + len, + module_idP, + 4, + P_RNTI, + UE_mac_inst[module_idP].rxFrame, + UE_mac_inst[module_idP].rxSubframe, 0, 0); + LOG_D(OPT, + "[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, P_RNTI, len); + } } #if defined(Rel10) || defined(Rel14) unsigned char *parse_mch_header(unsigned char *mac_header, - unsigned char *num_sdu, - unsigned char *rx_lcids, - unsigned short *rx_lengths, - unsigned short tb_length) + unsigned char *num_sdu, + unsigned char *rx_lcids, + unsigned short *rx_lengths, + unsigned short tb_length) { - unsigned char not_done=1, num_sdus=0, lcid, i; - unsigned char *mac_header_ptr = mac_header; - unsigned short length; - - 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 < SHORT_PADDING) {// subheader for MSI, MCCH or MTCH - if (not_done == 0) { // last MAC SDU, length is implicit - mac_header_ptr++; - length = tb_length- (mac_header_ptr - mac_header); - - for (i=0; i<num_sdus; i++) { - length -= rx_lengths[i]; - } - } else { // not the last MAC SDU - if ( ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {// subheader has length of 3octets - // length = ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L; - length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff); - mac_header_ptr += 3; - } else { // subheader has length of 2octets - length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L; - mac_header_ptr += 2; - } - } - - rx_lcids[num_sdus] = lcid; - rx_lengths[num_sdus] = length; - num_sdus++; - } else { // subheader for padding - // if (lcid == SHORT_PADDING) - mac_header_ptr++; - } - } - - *num_sdu = num_sdus; - return(mac_header_ptr); + unsigned char not_done = 1, num_sdus = 0, lcid, i; + unsigned char *mac_header_ptr = mac_header; + unsigned short length; + + 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 < SHORT_PADDING) { // subheader for MSI, MCCH or MTCH + if (not_done == 0) { // last MAC SDU, length is implicit + mac_header_ptr++; + length = tb_length - (mac_header_ptr - mac_header); + + for (i = 0; i < num_sdus; i++) { + length -= rx_lengths[i]; + } + } else { // not the last MAC SDU + if (((SCH_SUBHEADER_LONG *) mac_header_ptr)->F == 1) { // subheader has length of 3octets + // length = ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L; + length = + ((((SCH_SUBHEADER_LONG *) mac_header_ptr)-> + L_MSB & 0x7f) + << 8) | (((SCH_SUBHEADER_LONG *) mac_header_ptr)-> + L_LSB & 0xff); + mac_header_ptr += 3; + } else { // subheader has length of 2octets + length = ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L; + mac_header_ptr += 2; + } + } + + rx_lcids[num_sdus] = lcid; + rx_lengths[num_sdus] = length; + num_sdus++; + } else { // subheader for padding + // if (lcid == SHORT_PADDING) + mac_header_ptr++; + } + } + + *num_sdu = num_sdus; + return (mac_header_ptr); } // this function is for sending mch_sdu from phy to mac -void ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, uint8_t *sdu, uint16_t sdu_len, uint8_t eNB_index, uint8_t sync_area) +void +ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, + uint8_t * sdu, uint16_t sdu_len, uint8_t eNB_index, + uint8_t sync_area) { - unsigned char num_sdu, i, *payload_ptr; - unsigned char rx_lcids[NB_RB_MAX]; - unsigned short rx_lengths[NB_RB_MAX]; + unsigned char num_sdu, i, *payload_ptr; + unsigned char rx_lcids[NB_RB_MAX]; + unsigned short rx_lengths[NB_RB_MAX]; #if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].rx_mch_sdu); + start_meas(&UE_mac_inst[module_idP].rx_mch_sdu); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN); - - LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area); - LOG_D(MAC,"[UE %d] sdu: %x.%x\n", module_idP,sdu[0], sdu[1]); - LOG_D(MAC,"[UE %d] parse_mch_header, demultiplex\n",module_idP); - - payload_ptr = parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len); - LOG_D(MAC,"[UE %d] parse_mch_header, found %d sdus\n",module_idP,num_sdu); - - for (i=0; i<num_sdu; i++) { - if (rx_lcids[i] == MCH_SCHDL_INFO) { - if (UE_mac_inst[module_idP].mcch_status==1) { - LOG_I(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]); - // ??store necessary scheduling info to ue_mac_inst in order to - // calculate exact position of interested service (for the complex case has >1 mtch) - // set msi_status to 1 - UE_mac_inst[module_idP].msi_status = 1; - } - } else if (rx_lcids[i] == MCCH_LCHANID) { - LOG_I(MAC,"[UE %d] Frame %d : SDU %d MCH->MCCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, i, sync_area, eNB_index, rx_lengths[i]); - mac_rrc_data_ind(module_idP, - CC_id, - frameP,0, // unknown subframe - M_RNTI, - MCCH, - payload_ptr, rx_lengths[i], 0, eNB_index, sync_area); - } else if (rx_lcids[i] == MTCH) { - if (UE_mac_inst[module_idP].msi_status==1) { - LOG_I(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]); - - mac_rlc_data_ind( - module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_YES, - MTCH, /*+ (maxDRB + 3),*/ - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL); - - } - } else { - LOG_W(MAC,"[UE %d] Frame %d : unknown sdu %d rx_lcids[%d]=%d mcch status %d eNB %d \n", - module_idP, - frameP, - rx_lengths[i], - i, - rx_lcids[i], - UE_mac_inst[module_idP].mcch_status, eNB_index); - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN); - payload_ptr += rx_lengths[i]; - } + LOG_D(MAC, + "[UE %d] Frame %d : process the mch PDU for sync area %d \n", + module_idP, frameP, sync_area); + LOG_D(MAC, "[UE %d] sdu: %x.%x\n", module_idP, sdu[0], sdu[1]); + LOG_D(MAC, "[UE %d] parse_mch_header, demultiplex\n", module_idP); + + payload_ptr = + parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len); + LOG_D(MAC, "[UE %d] parse_mch_header, found %d sdus\n", module_idP, + num_sdu); + + for (i = 0; i < num_sdu; i++) { + if (rx_lcids[i] == MCH_SCHDL_INFO) { + if (UE_mac_inst[module_idP].mcch_status == 1) { + LOG_I(MAC, + "[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes)\n", + module_idP, frameP, sync_area, eNB_index, + rx_lengths[i]); + // ??store necessary scheduling info to ue_mac_inst in order to + // calculate exact position of interested service (for the complex case has >1 mtch) + // set msi_status to 1 + UE_mac_inst[module_idP].msi_status = 1; + } + } else if (rx_lcids[i] == MCCH_LCHANID) { + LOG_I(MAC, + "[UE %d] Frame %d : SDU %d MCH->MCCH for sync area %d (eNB %d, %d bytes)\n", + module_idP, frameP, i, sync_area, eNB_index, + rx_lengths[i]); + mac_rrc_data_ind(module_idP, CC_id, frameP, 0, // unknown subframe + M_RNTI, + MCCH, + payload_ptr, rx_lengths[i], 0, eNB_index, + sync_area); + } else if (rx_lcids[i] == MTCH) { + if (UE_mac_inst[module_idP].msi_status == 1) { + LOG_I(MAC, + "[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes)\n", + module_idP, frameP, sync_area, eNB_index, + rx_lengths[i]); + + mac_rlc_data_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index, frameP, ENB_FLAG_NO, MBMS_FLAG_YES, MTCH, /*+ (maxDRB + 3), */ + (char *) payload_ptr, rx_lengths[i], 1, + NULL); + + } + } else { + LOG_W(MAC, + "[UE %d] Frame %d : unknown sdu %d rx_lcids[%d]=%d mcch status %d eNB %d \n", + module_idP, frameP, rx_lengths[i], i, rx_lcids[i], + UE_mac_inst[module_idP].mcch_status, eNB_index); + } + + payload_ptr += rx_lengths[i]; + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu); + stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu); #endif } -int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index) +int8_t +ue_get_mbsfn_sf_alloction(module_id_t module_idP, + uint8_t mbsfn_sync_area, unsigned char eNB_index) { - // currently there is one-to-one mapping between sf allocation pattern and sync area - if (mbsfn_sync_area >= MAX_MBSFN_AREA) { - LOG_W( MAC, "[UE %"PRIu8"] MBSFN synchronization area %"PRIu8" out of range for eNB %"PRIu8"\n", module_idP, mbsfn_sync_area, eNB_index ); - return -1; - } else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) { - return mbsfn_sync_area; - } else { - LOG_W( MAC, "[UE %"PRIu8"] MBSFN Subframe Config pattern %"PRIu8" not found \n", module_idP, mbsfn_sync_area ); - return -1; - } + // currently there is one-to-one mapping between sf allocation pattern and sync area + if (mbsfn_sync_area >= MAX_MBSFN_AREA) { + LOG_W(MAC, + "[UE %" PRIu8 "] MBSFN synchronization area %" PRIu8 + " out of range for eNB %" PRIu8 "\n", module_idP, + mbsfn_sync_area, eNB_index); + return -1; + } else if (UE_mac_inst[module_idP]. + mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) { + return mbsfn_sync_area; + } else { + LOG_W(MAC, + "[UE %" PRIu8 "] MBSFN Subframe Config pattern %" PRIu8 + " not found \n", module_idP, mbsfn_sync_area); + return -1; + } } -int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active) +int +ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, + uint32_t subframe, uint8_t eNB_index, uint8_t * sync_area, + uint8_t * mcch_active) { - int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1; - int mcch_flag=0, mtch_flag=0, msi_flag=0; - int mbsfn_period = 0;// 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); - int mcch_period = 0;// 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); - int mch_scheduling_period = -1; + int i = 0, j = 0, ii = 0, msi_pos = 0, mcch_mcs = -1; + int mcch_flag = 0, mtch_flag = 0, msi_flag = 0; + int mbsfn_period = 0; // 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); + int mcch_period = 0; // 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); + int mch_scheduling_period = -1; - int frame_FDD=1; + int frame_FDD = 1; #if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].ue_query_mch); + start_meas(&UE_mac_inst[module_idP].ue_query_mch); #endif - if (UE_mac_inst[module_idP].pmch_Config[0]) { - mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9); - } - - for (i=0; - i< UE_mac_inst[module_idP].num_active_mbsfn_area; - i++ ) { - // assume, that there is always a mapping - if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1) { - return -1; // continue; + if (UE_mac_inst[module_idP].pmch_Config[0]) { + mch_scheduling_period = + 8 << (UE_mac_inst[module_idP]. + pmch_Config[0]->mch_SchedulingPeriod_r9); } - ii=0; - msi_pos=0; - mbsfn_period = 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); - mcch_period = 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); + for (i = 0; i < UE_mac_inst[module_idP].num_active_mbsfn_area; i++) { + // assume, that there is always a mapping + if ((j = + ue_get_mbsfn_sf_alloction(module_idP, i, eNB_index)) == -1) { + return -1; // continue; + } + + ii = 0; + msi_pos = 0; + mbsfn_period = + 1 << (UE_mac_inst[module_idP]. + mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); + mcch_period = + 32 << (UE_mac_inst[module_idP]. + mbsfn_AreaInfo[0]->mcch_Config_r9. + mcch_RepetitionPeriod_r9); + + LOG_D(MAC, + "[UE %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,mac sched period (%d,%ld))\n", + module_idP, frameP, subframe, i, + UE_mac_inst[module_idP].num_active_mbsfn_area, j, + UE_mac_inst[module_idP].num_sf_allocation_pattern, + mbsfn_period, mcch_period, mch_scheduling_period, + UE_mac_inst[module_idP]. + mbsfn_SubframeConfig[j]->radioframeAllocationOffset); + + // get the real MCS value + switch (UE_mac_inst[module_idP].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; + } + + if (frameP % mbsfn_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP + if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format + + if (UE_mac_inst[module_idP].pmch_Config[0]) { + // Find the first subframe in this MCH to transmit MSI + if (frameP % mch_scheduling_period == + UE_mac_inst[module_idP]. + mbsfn_SubframeConfig + [j]->radioframeAllocationOffset) { + while (ii == 0) { + ii = UE_mac_inst[module_idP]. + mbsfn_SubframeConfig[j]-> + subframeAllocation.choice. + oneFrame.buf[0] & (0x80 >> msi_pos); + msi_pos++; + } + } + } + + if (UE_mac_inst[module_idP].tdd_Config == NULL) + frame_FDD = 1; + else + frame_FDD = 0; + // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 + switch (subframe) { + case 1: + if (frame_FDD == 1) { + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { + if (msi_pos == 1) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.sf_AllocInfo_r9. + buf[0] & MBSFN_FDD_SF1) == + MBSFN_FDD_SF1)) { + mcch_flag = 1; + } + + mtch_flag = 1; + } + } - LOG_D(MAC, - "[UE %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,mac sched period (%d,%ld))\n", - module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area, - j,UE_mac_inst[module_idP].num_sf_allocation_pattern,mbsfn_period,mcch_period, - mch_scheduling_period,UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset); - - // get the real MCS value - switch (UE_mac_inst[module_idP].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; - } - - if (frameP % mbsfn_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP - if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format - - if (UE_mac_inst[module_idP].pmch_Config[0]) { - // Find the first subframe in this MCH to transmit MSI - if (frameP % mch_scheduling_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) { - while (ii == 0) { - ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos); - msi_pos++; - } - } - } - - if (UE_mac_inst[module_idP].tdd_Config == NULL) frame_FDD=1; - else frame_FDD=0; - // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 - switch (subframe) { - case 1: - if (frame_FDD==1) { - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { - if (msi_pos == 1) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==1) { - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==0) { //TDD - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { - if (msi_pos == 1) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==0) { - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==1) { - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==0) { // TDD - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==0) { //TDD - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { - if (msi_pos == 6) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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 (frame_FDD==0) { - if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) && - ((UE_mac_inst[module_idP].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,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", - module_idP, frameP, subframe,i,j,msi_flag,mcch_flag,mtch_flag); - - *sync_area=i; - break; - } - } else { // four-frameP format - } - } - } // end of for + break; + + case 2: + if (frame_FDD == 1) { + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { + if (msi_pos == 2) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 0) { //TDD + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { + if (msi_pos == 1) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { + if (msi_pos == 3) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 0) { + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { + if (msi_pos == 2) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 1) { + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { + if (msi_pos == 4) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 0) { // TDD + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { + if (msi_pos == 3) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { + if (msi_pos == 5) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 0) { //TDD + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { + if (msi_pos == 4) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { + if (msi_pos == 6) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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 (frame_FDD == 0) { + if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig + [j]->subframeAllocation.choice.oneFrame. + buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { + if (msi_pos == 5) { + msi_flag = 1; + } + + if ((frameP % mcch_period == + UE_mac_inst[module_idP].mbsfn_AreaInfo + [i]->mcch_Config_r9.mcch_Offset_r9) + && + ((UE_mac_inst[module_idP].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, + "[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", + module_idP, frameP, subframe, i, j, msi_flag, + mcch_flag, mtch_flag); + + *sync_area = i; + break; + } + } else { // four-frameP format + } + } + } // end of for #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_query_mch); + stop_meas(&UE_mac_inst[module_idP].ue_query_mch); #endif - if ( (mcch_flag==1)) { // || (msi_flag==1)) - *mcch_active=1; - } - - if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ) { - return mcch_mcs; - } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status==1)) { - return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9; - } else { - return -1; - } + if ((mcch_flag == 1)) { // || (msi_flag==1)) + *mcch_active = 1; + } + + if ((mcch_flag == 1) + || ((msi_flag == 1) && (UE_mac_inst[module_idP].mcch_status == 1))) { + return mcch_mcs; + } else if ((mtch_flag == 1) + && (UE_mac_inst[module_idP].msi_status == 1)) { + return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9; + } else { + return -1; + } } #endif -unsigned char generate_ulsch_header(uint8_t *mac_header, - uint8_t num_sdus, - uint8_t short_padding, - uint16_t *sdu_lengths, - uint8_t *sdu_lcids, - POWER_HEADROOM_CMD *power_headroom, - uint16_t *crnti, - BSR_SHORT *truncated_bsr, - BSR_SHORT *short_bsr, - BSR_LONG *long_bsr, - unsigned short post_padding) +unsigned char +generate_ulsch_header(uint8_t * mac_header, + uint8_t num_sdus, + uint8_t short_padding, + uint16_t * sdu_lengths, + uint8_t * sdu_lcids, + POWER_HEADROOM_CMD * power_headroom, + uint16_t * crnti, + BSR_SHORT * truncated_bsr, + BSR_SHORT * short_bsr, + BSR_LONG * long_bsr, unsigned short post_padding) { - SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header; - unsigned char first_element=0,last_size=0,i; - unsigned char mac_header_control_elements[16],*ce_ptr; + SCH_SUBHEADER_FIXED *mac_header_ptr = + (SCH_SUBHEADER_FIXED *) mac_header; + unsigned char first_element = 0, last_size = 0, i; + unsigned char mac_header_control_elements[16], *ce_ptr; - LOG_D(MAC,"[UE] Generate ULSCH : num_sdus %d\n",num_sdus); + LOG_D(MAC, "[UE] Generate ULSCH : num_sdus %d\n", num_sdus); #ifdef DEBUG_HEADER_PARSING - for (i=0; i<num_sdus; i++) { - LOG_T(MAC,"[UE] sdu %d : lcid %d length %d",i,sdu_lcids[i],sdu_lengths[i]); - } + for (i = 0; i < num_sdus; i++) { + LOG_T(MAC, "[UE] sdu %d : lcid %d length %d", i, sdu_lcids[i], + sdu_lengths[i]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - 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; - } - - if (power_headroom) { - if (first_element>0) { - mac_header_ptr->E = 1; - mac_header_ptr++; - } else { - first_element=1; + 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; } - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = POWER_HEADROOM; - last_size=1; - *((POWER_HEADROOM_CMD *)ce_ptr)=(*power_headroom); - ce_ptr+=sizeof(POWER_HEADROOM_CMD); - LOG_D(MAC, "phr header size %zu\n",sizeof(POWER_HEADROOM_CMD)); - } + if (power_headroom) { + 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 = POWER_HEADROOM; + last_size = 1; + *((POWER_HEADROOM_CMD *) ce_ptr) = (*power_headroom); + ce_ptr += sizeof(POWER_HEADROOM_CMD); + LOG_D(MAC, "phr header size %zu\n", sizeof(POWER_HEADROOM_CMD)); + } - if (crnti) { + if (crnti) { #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] CRNTI : %x (first_element %d)\n",*crnti,first_element); + LOG_D(MAC, "[UE] CRNTI : %x (first_element %d)\n", *crnti, + first_element); #endif - 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 = CRNTI; - last_size=1; - *((uint16_t *)ce_ptr)=(*crnti); - ce_ptr+=sizeof(uint16_t); - // printf("offset %d\n",ce_ptr-mac_header_control_elements); - } - - if (truncated_bsr) { - if (first_element>0) { - mac_header_ptr->E = 1; - /* - 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); - */ - mac_header_ptr++; - } else { - first_element=1; + 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 = CRNTI; + last_size = 1; + *((uint16_t *) ce_ptr) = (*crnti); + ce_ptr += sizeof(uint16_t); + // printf("offset %d\n",ce_ptr-mac_header_control_elements); } + if (truncated_bsr) { + if (first_element > 0) { + mac_header_ptr->E = 1; + /* + 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); + */ + mac_header_ptr++; + } else { + first_element = 1; + } + #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] Scheduler Truncated BSR Header\n"); + LOG_D(MAC, "[UE] Scheduler Truncated BSR Header\n"); #endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = TRUNCATED_BSR; - last_size=1; - *((BSR_TRUNCATED *)ce_ptr)=(*truncated_bsr); - ce_ptr+=sizeof(BSR_TRUNCATED); - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - - } else if (short_bsr) { - if (first_element>0) { - mac_header_ptr->E = 1; - /* - 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); - */ - mac_header_ptr++; - } else { - first_element=1; - } + mac_header_ptr->R = 0; + mac_header_ptr->E = 0; + mac_header_ptr->LCID = TRUNCATED_BSR; + last_size = 1; + *((BSR_TRUNCATED *) ce_ptr) = (*truncated_bsr); + ce_ptr += sizeof(BSR_TRUNCATED); + // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); + + } else if (short_bsr) { + if (first_element > 0) { + mac_header_ptr->E = 1; + /* + 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); + */ + mac_header_ptr++; + } else { + first_element = 1; + } #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] Scheduler SHORT BSR Header\n"); + LOG_D(MAC, "[UE] Scheduler SHORT BSR Header\n"); #endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = SHORT_BSR; - last_size=1; - *((BSR_SHORT *)ce_ptr)=(*short_bsr); - ce_ptr+=sizeof(BSR_SHORT); - - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - } else if (long_bsr) { - if (first_element>0) { - mac_header_ptr->E = 1; - /* - 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); - */ - mac_header_ptr++; - } else { - first_element=1; - } + mac_header_ptr->R = 0; + mac_header_ptr->E = 0; + mac_header_ptr->LCID = SHORT_BSR; + last_size = 1; + *((BSR_SHORT *) ce_ptr) = (*short_bsr); + ce_ptr += sizeof(BSR_SHORT); + + // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); + } else if (long_bsr) { + if (first_element > 0) { + mac_header_ptr->E = 1; + /* + 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); + */ + mac_header_ptr++; + } else { + first_element = 1; + } #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] Scheduler Long BSR Header\n"); + LOG_D(MAC, "[UE] Scheduler Long BSR Header\n"); #endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = LONG_BSR; - last_size=1; - - *(ce_ptr) = (long_bsr->Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4); - *(ce_ptr + 1) = ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr->Buffer_size2 & 0x3C) >> 2); - *(ce_ptr + 2) = ((long_bsr->Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F); - ce_ptr += BSR_LONG_SIZE; - - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - } + mac_header_ptr->R = 0; + mac_header_ptr->E = 0; + mac_header_ptr->LCID = LONG_BSR; + last_size = 1; + + *(ce_ptr) = + (long_bsr-> + Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4); + *(ce_ptr + 1) = + ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr-> + Buffer_size2 & 0x3C) + >> 2); + *(ce_ptr + 2) = + ((long_bsr-> + Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F); + ce_ptr += BSR_LONG_SIZE; + + // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); + } + // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); - // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); + for (i = 0; i < num_sdus; i++) { +#ifdef DEBUG_HEADER_PARSING + LOG_T(MAC, "[UE] sdu subheader %d (lcid %d, %d bytes)\n", i, + sdu_lcids[i], sdu_lengths[i]); +#endif - for (i=0; i<num_sdus; i++) { + if ((i == (num_sdus - 1)) + && ((short_padding) || (post_padding == 0))) { + if (first_element > 0) { + mac_header_ptr->E = 1; #ifdef DEBUG_HEADER_PARSING - LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]); + LOG_D(MAC, "[UE] 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); #endif + mac_header_ptr += last_size; + } + mac_header_ptr->R = 0; + mac_header_ptr->E = 0; + mac_header_ptr->LCID = sdu_lcids[i]; + } else { + if ((first_element > 0)) { + mac_header_ptr->E = 1; +#ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] 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); +#endif + mac_header_ptr += last_size; + // printf("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; // 3 + ((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; +#ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] short sdu\n"); + LOG_T(MAC, + "[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n", + ((uint16_t *) mac_header_ptr)[0], + ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->R, + ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->E, + ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->LCID, + ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F, + ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L); +#endif + } 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, "[UE] long sdu\n"); +#endif + } + } + } + + 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++; + //mac_header_ptr=last_size; // FIXME: should be ++ + } - if ((i == (num_sdus - 1)) && ((short_padding) || (post_padding == 0))) { - if (first_element>0) { - mac_header_ptr->E = 1; - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] 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); - #endif - mac_header_ptr+=last_size; - } - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = sdu_lcids[i]; - } - else { - if ((first_element>0)) { - mac_header_ptr->E = 1; - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] 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); - #endif - mac_header_ptr+=last_size; - // printf("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; // 3 - ((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; - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC,"[UE] short sdu\n"); - LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n", - ((uint16_t*)mac_header_ptr)[0], - ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R, - ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E, - ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID, - ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F, - ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L); - #endif - } 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,"[UE] long sdu\n"); - #endif - } - } - } - - 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++; - //mac_header_ptr=last_size; // FIXME: should be ++ - } - - - if ((ce_ptr-mac_header_control_elements) > 0) { - 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); - } + if ((ce_ptr - mac_header_control_elements) > 0) { + 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); + } #ifdef DEBUG_HEADER_PARSING - LOG_T(MAC," [UE] header : "); + LOG_T(MAC, " [UE] header : "); - for (i=0; i<((unsigned char*)mac_header_ptr - mac_header); i++) { - LOG_T(MAC,"%2x.",mac_header[i]); - } + for (i = 0; i < ((unsigned char *) mac_header_ptr - mac_header); i++) { + LOG_T(MAC, "%2x.", mac_header[i]); + } - LOG_T(MAC,"\n"); + LOG_T(MAC, "\n"); #endif - return((unsigned char*)mac_header_ptr - mac_header); + return ((unsigned char *) mac_header_ptr - mac_header); } -void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen, uint8_t *access_mode) +void +ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * ulsch_buffer, uint16_t buflen, uint8_t * access_mode) { - uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ; - uint16_t buflen_remain = 0; - uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0; - uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0; - uint8_t lcid=0,lcid_rlc_pdu_count=0; - boolean_t is_lcid_processed = FALSE; - boolean_t is_all_lcid_processed = FALSE; - uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t payload_offset=0,num_sdus=0; - uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES]; - uint16_t sdu_length_total=0; - BSR_SHORT bsr_short,bsr_truncated; - BSR_LONG bsr_long; - BSR_SHORT *bsr_s=&bsr_short; - BSR_LONG *bsr_l=&bsr_long; - BSR_SHORT *bsr_t=&bsr_truncated; - POWER_HEADROOM_CMD phr; - POWER_HEADROOM_CMD *phr_p=&phr; - unsigned short short_padding=0, post_padding=0, padding_len=0; - int j; // used for padding - // Compute header length - int lcg_id = 0; - int lcg_id_bsr_trunc = 0; - int highest_priority = 16; - int num_lcg_id_with_data = 0; - rlc_buffer_occupancy_t lcid_buffer_occupancy_old=0, lcid_buffer_occupancy_new=0; - - LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", - module_idP, frameP, subframe, buflen); - - - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); + uint8_t total_rlc_pdu_header_len = 0, rlc_pdu_header_len_last = 0; + uint16_t buflen_remain = 0; + uint8_t bsr_len = 0, bsr_ce_len = 0, bsr_header_len = 0; + uint8_t phr_header_len = 0, phr_ce_len = 0, phr_len = 0; + uint8_t lcid = 0, lcid_rlc_pdu_count = 0; + boolean_t is_lcid_processed = FALSE; + boolean_t is_all_lcid_processed = FALSE; + uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t payload_offset = 0, num_sdus = 0; + uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES]; + uint16_t sdu_length_total = 0; + BSR_SHORT bsr_short, bsr_truncated; + BSR_LONG bsr_long; + BSR_SHORT *bsr_s = &bsr_short; + BSR_LONG *bsr_l = &bsr_long; + BSR_SHORT *bsr_t = &bsr_truncated; + POWER_HEADROOM_CMD phr; + POWER_HEADROOM_CMD *phr_p = &phr; + unsigned short short_padding = 0, post_padding = 0, padding_len = 0; + int j; // used for padding + // Compute header length + int lcg_id = 0; + int lcg_id_bsr_trunc = 0; + int highest_priority = 16; + int num_lcg_id_with_data = 0; + rlc_buffer_occupancy_t lcid_buffer_occupancy_old = + 0, lcid_buffer_occupancy_new = 0; + + LOG_D(MAC, + "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", + module_idP, frameP, subframe, buflen); + + + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); #if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); + start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_IN); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_IN); #ifdef CBA - if (*access_mode==CBA_ACCESS) { - LOG_D(MAC,"[UE %d] frameP %d subframe %d try CBA transmission\n", - module_idP, frameP, subframe); + if (*access_mode == CBA_ACCESS) { + LOG_D(MAC, "[UE %d] frameP %d subframe %d try CBA transmission\n", + module_idP, frameP, subframe); + + //if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_EMPTY) + if (cba_access(module_idP, frameP, subframe, eNB_index, buflen) == + 0) { + *access_mode = POSTPONED_ACCESS; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT); + return; + } + + LOG_I(MAC, + "[UE %d] frameP %d subframe %d CBA transmission oppurtunity, tbs %d\n", + module_idP, frameP, subframe, buflen); + } +#endif + bsr_header_len = 0; + phr_header_len = 1; //sizeof(SCH_SUBHEADER_FIXED); + + while (lcg_id < MAX_NUM_LCGID) { + if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]) { + num_lcg_id_with_data++; + } + lcg_id++; + } + + if (num_lcg_id_with_data) { + LOG_D(MAC, + "[UE %d] MAC Tx data pending at frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n", + module_idP, frameP, subframe, num_lcg_id_with_data, + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3], + UE_mac_inst[module_idP].BSR_reporting_active, buflen); - //if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_EMPTY) - if (cba_access(module_idP,frameP,subframe,eNB_index,buflen)==0) { - *access_mode=POSTPONED_ACCESS; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT); - return; } + //Restart ReTxBSR Timer at new grant indication (36.321) + if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != + MAC_UE_BSR_TIMER_NOT_RUNNING) { + UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = + get_sf_retxBSRTimer(UE_mac_inst[module_idP]. + scheduling_info.retxBSR_Timer); + } + // periodicBSR-Timer expires, trigger BSR + if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != + PeriodicBSR_Timer_r12_infinity) + && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)) { + // Trigger BSR Periodic + UE_mac_inst[module_idP].BSR_reporting_active |= + BSR_TRIGGER_PERIODIC; + + LOG_D(MAC, + "[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n", + module_idP, frameP, subframe, buflen); - LOG_I(MAC,"[UE %d] frameP %d subframe %d CBA transmission oppurtunity, tbs %d\n", - module_idP, frameP, subframe,buflen); - } + } + //Compute BSR Length if Regular or Periodic BSR is triggered + //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx + if (UE_mac_inst[module_idP].BSR_reporting_active) { + + AssertFatal((UE_mac_inst[module_idP].BSR_reporting_active & + BSR_TRIGGER_PADDING) == 0, + "Inconsistent BSR Trigger=%d !\n", + UE_mac_inst[module_idP].BSR_reporting_active); + + if (buflen >= 4) { + //A Regular or Periodic BSR can only be sent if TBS >= 4 as transmitting only a BSR is not allowed if UE has data to transmit + bsr_header_len = 1; + + if (num_lcg_id_with_data <= 1) { + bsr_ce_len = sizeof(BSR_SHORT); //1 byte + } else { + bsr_ce_len = BSR_LONG_SIZE; //3 bytes + } + } + } -#endif - bsr_header_len = 0; - phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED); - - while (lcg_id < MAX_NUM_LCGID) { - if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){ - num_lcg_id_with_data ++; - } - lcg_id ++; - } - - if (num_lcg_id_with_data){ - LOG_D(MAC,"[UE %d] MAC Tx data pending at frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n", - module_idP, - frameP, - subframe, - num_lcg_id_with_data, - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3], - UE_mac_inst[module_idP].BSR_reporting_active, buflen); - - } - //Restart ReTxBSR Timer at new grant indication (36.321) - if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING){ - UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer); - } - - // periodicBSR-Timer expires, trigger BSR - if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity) - && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)){ - // Trigger BSR Periodic - UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC; - - LOG_D(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n", - module_idP, frameP, subframe, buflen); - - } - - //Compute BSR Length if Regular or Periodic BSR is triggered - //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx - if (UE_mac_inst[module_idP].BSR_reporting_active){ - - AssertFatal ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING) == 0 , "Inconsistent BSR Trigger=%d !\n", - UE_mac_inst[module_idP].BSR_reporting_active); - - if (buflen >= 4){ - //A Regular or Periodic BSR can only be sent if TBS >= 4 as transmitting only a BSR is not allowed if UE has data to transmit - bsr_header_len = 1; - - if (num_lcg_id_with_data <= 1){ - bsr_ce_len = sizeof(BSR_SHORT); //1 byte - } - else{ - bsr_ce_len = BSR_LONG_SIZE; //3 bytes - } - } - } - - bsr_len = bsr_ce_len + bsr_header_len; - - phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0; - if ((phr_ce_len > 0) && ((phr_ce_len + phr_header_len + bsr_len) <= buflen)){ - phr_len = phr_ce_len + phr_header_len; - LOG_D(MAC,"[UE %d] header size info: PHR len %d (ce%d,hdr%d) buff_len %d\n", - module_idP, phr_len, phr_ce_len, phr_header_len, buflen); - } else { - phr_len=0; - phr_header_len = 0; - phr_ce_len = 0; - } - - // check for UL bandwidth requests and add SR control element - - // check for UL bandwidth requests and add SR control element - - // Check for DCCH first -// TO DO: Multiplex in the order defined by the logical channel prioritization -for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid++) { - if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) { + bsr_len = bsr_ce_len + bsr_header_len; + + phr_ce_len = + (UE_mac_inst[module_idP].PHR_reporting_active == + 1) ? 1 /* sizeof(POWER_HEADROOM_CMD) */ : 0; + if ((phr_ce_len > 0) + && ((phr_ce_len + phr_header_len + bsr_len) <= buflen)) { + phr_len = phr_ce_len + phr_header_len; + LOG_D(MAC, + "[UE %d] header size info: PHR len %d (ce%d,hdr%d) buff_len %d\n", + module_idP, phr_len, phr_ce_len, phr_header_len, buflen); + } else { + phr_len = 0; + phr_header_len = 0; + phr_ce_len = 0; + } - lcid_rlc_pdu_count = 0; - is_lcid_processed = FALSE; - lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - subframe, - ENB_FLAG_NO, - lcid); + // check for UL bandwidth requests and add SR control element - lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; + // check for UL bandwidth requests and add SR control element - AssertFatal (lcid_buffer_occupancy_new == UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid], "LCID=%d RLC has BO %d bytes but MAC has stored %d bytes\n", - lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]); + // Check for DCCH first +// TO DO: Multiplex in the order defined by the logical channel prioritization + for (lcid = DCCH; + (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE); lcid++) + { + if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == + LCID_NOT_EMPTY) { + + lcid_rlc_pdu_count = 0; + is_lcid_processed = FALSE; + lcid_buffer_occupancy_old = + mac_rlc_get_buffer_occupancy_ind(module_idP, + UE_mac_inst[module_idP]. + crnti, eNB_index, frameP, + subframe, ENB_FLAG_NO, + lcid); + + lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; + + AssertFatal(lcid_buffer_occupancy_new == + UE_mac_inst[module_idP]. + scheduling_info.LCID_buffer_remain[lcid], + "LCID=%d RLC has BO %d bytes but MAC has stored %d bytes\n", + lcid, lcid_buffer_occupancy_new, + UE_mac_inst[module_idP]. + scheduling_info.LCID_buffer_remain[lcid]); + + AssertFatal(lcid_buffer_occupancy_new <= + UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID + [lcid]], + "LCID=%d RLC has more BO %d bytes than BSR = %d bytes\n", + lcid, lcid_buffer_occupancy_new, + UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID + [lcid]]); + + + //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data + //Adjust at the end of the loop + while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) + && (bsr_len + phr_len + total_rlc_pdu_header_len + + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) + { + + // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU + if ((usim_test == 0) && (lcid == DCCH1) + && (lcid_rlc_pdu_count == 0) && (num_sdus)) { + + // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed + break; + } + + buflen_remain = + buflen - (bsr_len + phr_len + + total_rlc_pdu_header_len + sdu_length_total + + 1); + + + LOG_D(MAC, + "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " + "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", + module_idP, frameP, lcid, lcid_buffer_occupancy_new, + buflen, bsr_len, phr_len, sdu_length_total, + total_rlc_pdu_header_len, + UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID + [lcid]]); + + + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + UE_mac_inst + [module_idP]. + crnti, eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + lcid, + buflen_remain, + (char *) + &ulsch_buff + [sdu_length_total]); + + + AssertFatal(buflen_remain >= sdu_lengths[num_sdus], + "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", + lcid, sdu_lengths[num_sdus], buflen_remain); + + + if (sdu_lengths[num_sdus]) { + sdu_length_total += sdu_lengths[num_sdus]; + sdu_lcids[num_sdus] = lcid; + LOG_D(MAC, + "[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n", + module_idP, sdu_lengths[num_sdus], lcid); + + if (buflen == + (bsr_len + phr_len + total_rlc_pdu_header_len + + sdu_length_total + 1)) { + //No more remaining TBS after this PDU + //exit the function + rlc_pdu_header_len_last = 1; + is_lcid_processed = TRUE; + is_all_lcid_processed = TRUE; + } else { + rlc_pdu_header_len_last = + (sdu_lengths[num_sdus] > 128) ? 3 : 2; + + //Change to 1 byte if it does not fit in the TBS, ie last PDU + if (buflen <= + (bsr_len + phr_len + total_rlc_pdu_header_len + + rlc_pdu_header_len_last + sdu_length_total)) { + rlc_pdu_header_len_last = 1; + is_lcid_processed = TRUE; + is_all_lcid_processed = TRUE; + } + } + + //Update number of SDU + num_sdus++; + + //Update total MAC Header size for RLC PDUs and save last one + total_rlc_pdu_header_len += rlc_pdu_header_len_last; + + lcid_rlc_pdu_count++; + } else { + /* avoid infinite loop ... */ + is_lcid_processed = TRUE; + } + + /* Get updated BO after multiplexing this PDU */ + lcid_buffer_occupancy_new = + mac_rlc_get_buffer_occupancy_ind(module_idP, + UE_mac_inst + [module_idP].crnti, + eNB_index, frameP, + subframe, ENB_FLAG_NO, + lcid); + + is_lcid_processed = (is_lcid_processed) + || (lcid_buffer_occupancy_new <= 0); + } + + //Update Buffer remain and BSR bytes after transmission + + AssertFatal(lcid_buffer_occupancy_new <= + lcid_buffer_occupancy_old, + "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n", + lcid_buffer_occupancy_new, + lcid_buffer_occupancy_old, lcid, + lcid_rlc_pdu_count, frameP, subframe); + + UE_mac_inst[module_idP].scheduling_info. + LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new; + UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID[lcid]] += + (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old); + + //Update the number of LCGID with data as BSR shall reflect status after BSR transmission + if ((num_lcg_id_with_data > 1) + && (UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. + scheduling_info.LCGID[lcid]] + == 0)) { + num_lcg_id_with_data--; + // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 + if ((bsr_len) && (num_lcg_id_with_data == 1)) { + bsr_ce_len = sizeof(BSR_SHORT); + bsr_len = bsr_ce_len + bsr_header_len; + } + } + + + UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = + LCID_EMPTY; + } + } - AssertFatal (lcid_buffer_occupancy_new <= UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], "LCID=%d RLC has more BO %d bytes than BSR = %d bytes\n", - lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); - //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data - //Adjust at the end of the loop - while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { + // Compute BSR Values and update Nb LCGID with data after multiplexing + num_lcg_id_with_data = 0; + lcg_id_bsr_trunc = 0; + for (lcg_id = 0; lcg_id < MAX_NUM_LCGID; lcg_id++) { + UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] = + locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, + UE_mac_inst + [module_idP].scheduling_info. + BSR_bytes[lcg_id]); - // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU - if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) { + if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]) { + num_lcg_id_with_data++; + lcg_id_bsr_trunc = lcg_id; + } + } - // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed - break; - } - buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); + if (bsr_ce_len) { + //Print updated BSR when sent + LOG_D(MAC, + "[UE %d] Remaining Buffer after Tx frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n", + module_idP, frameP, subframe, num_lcg_id_with_data, + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2], + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3], + UE_mac_inst[module_idP].BSR_reporting_active, buflen); + + LOG_D(MAC, + "[UE %d] Frame %d Subframe %d TX BSR Regular or Periodic size=%d BSR0=%d BSR1=%d BSR2=%d BSR3=%d\n", + module_idP, frameP, subframe, bsr_ce_len, + UE_mac_inst[module_idP].scheduling_info.BSR[0], + UE_mac_inst[module_idP].scheduling_info.BSR[1], + UE_mac_inst[module_idP].scheduling_info.BSR[2], + UE_mac_inst[module_idP].scheduling_info.BSR[3]); + } + // build PHR and update the timers + if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) { + phr_p->PH = get_phr_mapping(module_idP, CC_id, eNB_index); + phr_p->R = 0; + LOG_D(MAC, + "[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n", + module_idP, frameP, get_PHR(module_idP, CC_id, eNB_index), + phr_p->PH, POWER_HEADROOM); + update_phr(module_idP, CC_id); + } else { + phr_p = NULL; + } + LOG_T(MAC, "[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", + module_idP, frameP, bsr_s, bsr_l, phr_p); - LOG_D(MAC, "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " - "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", - module_idP,frameP, lcid,lcid_buffer_occupancy_new,buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); + // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order + // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 + /* For Padding BSR: + - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader: + - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission; + - else report Short BSR. + - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. + */ + if (sdu_length_total) { + padding_len = + buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - + rlc_pdu_header_len_last + sdu_length_total + 1); + } else { + padding_len = buflen - (bsr_len + phr_len); + } - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - buflen_remain, - (char *)&ulsch_buff[sdu_length_total]); - - - AssertFatal (buflen_remain >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid,sdu_lengths[num_sdus],buflen_remain); - - - if (sdu_lengths[num_sdus]) - { - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n",module_idP,sdu_lengths[num_sdus],lcid); - - if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) { - //No more remaining TBS after this PDU - //exit the function - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; - } - else { - rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ; - - //Change to 1 byte if it does not fit in the TBS, ie last PDU - if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) { - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; - } - } - - //Update number of SDU - num_sdus ++; - - //Update total MAC Header size for RLC PDUs and save last one - total_rlc_pdu_header_len += rlc_pdu_header_len_last; - - lcid_rlc_pdu_count ++; - } - else - { - /* avoid infinite loop ... */ - is_lcid_processed = TRUE; - } - - /* Get updated BO after multiplexing this PDU */ - lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - subframe, - ENB_FLAG_NO, - lcid); - - is_lcid_processed = (is_lcid_processed) || (lcid_buffer_occupancy_new <= 0); - } - - //Update Buffer remain and BSR bytes after transmission - - AssertFatal (lcid_buffer_occupancy_new <= lcid_buffer_occupancy_old, "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n", - lcid_buffer_occupancy_new,lcid_buffer_occupancy_old,lcid,lcid_rlc_pdu_count,frameP,subframe); - - UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new; - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] += (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old); - - //Update the number of LCGID with data as BSR shall reflect status after BSR transmission - if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)) - { - num_lcg_id_with_data --; - // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 - if ((bsr_len) && (num_lcg_id_with_data == 1)) - { - bsr_ce_len = sizeof(BSR_SHORT); - bsr_len = bsr_ce_len + bsr_header_len; - } - } - - - UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY; - } - } - - - - // Compute BSR Values and update Nb LCGID with data after multiplexing - num_lcg_id_with_data = 0; - lcg_id_bsr_trunc = 0; - for (lcg_id=0;lcg_id<MAX_NUM_LCGID;lcg_id++){ - UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] = locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]); - - if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){ - num_lcg_id_with_data ++; - lcg_id_bsr_trunc = lcg_id; - } - } - - - if (bsr_ce_len) { - //Print updated BSR when sent - LOG_D(MAC,"[UE %d] Remaining Buffer after Tx frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n", - module_idP, - frameP, - subframe, - num_lcg_id_with_data, - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2], - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3], - UE_mac_inst[module_idP].BSR_reporting_active, buflen); - - LOG_D(MAC,"[UE %d] Frame %d Subframe %d TX BSR Regular or Periodic size=%d BSR0=%d BSR1=%d BSR2=%d BSR3=%d\n",module_idP,frameP,subframe,bsr_ce_len, - UE_mac_inst[module_idP].scheduling_info.BSR[0], - UE_mac_inst[module_idP].scheduling_info.BSR[1], - UE_mac_inst[module_idP].scheduling_info.BSR[2], - UE_mac_inst[module_idP].scheduling_info.BSR[3]); - } - - - // build PHR and update the timers - if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) { - phr_p->PH = get_phr_mapping(module_idP,CC_id,eNB_index); - phr_p->R = 0; - LOG_D(MAC,"[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n", - module_idP,frameP, get_PHR(module_idP,CC_id,eNB_index), phr_p->PH,POWER_HEADROOM); - update_phr(module_idP,CC_id); - } else { - phr_p=NULL; - } - - LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p); - - - // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order - // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 - /* For Padding BSR: - - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader: - - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission; - - else report Short BSR. - - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. - */ - if (sdu_length_total) { - padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1); - } - else { - padding_len = buflen - (bsr_len + phr_len); - } - - - if ((padding_len) && (bsr_len == 0)) - { - /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR*/ - if (padding_len >= (1+BSR_LONG_SIZE)) - { - bsr_ce_len = BSR_LONG_SIZE; - bsr_header_len = 1; - // Trigger BSR Padding - UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING; - - - } else if (padding_len >= (1+sizeof(BSR_SHORT))) { - bsr_ce_len = sizeof(BSR_SHORT); - bsr_header_len = 1; - - if (num_lcg_id_with_data > 1) - { - // REPORT TRUNCATED BSR - //Get LCGID of highest priority LCID with data - for (lcid=DCCH; lcid < MAX_NUM_LCID ; lcid++) { - if (UE_mac_inst[module_idP].logicalChannelConfig[lcid] != NULL) { - lcg_id = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]; - - if ((lcg_id < MAX_NUM_LCGID) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]) - && (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)) { - highest_priority = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority; - lcg_id_bsr_trunc = lcg_id; - } - } - } - } - else - { - //Report SHORT BSR, clear bsr_t - bsr_t = NULL; - } - - // Trigger BSR Padding - UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING; - } - bsr_len = bsr_header_len + bsr_ce_len; - } - - //Fill BSR Infos - if (bsr_ce_len == 0 ) { - bsr_s = NULL; - bsr_l = NULL; - bsr_t = NULL; - } else if (bsr_ce_len == BSR_LONG_SIZE) { - bsr_s = NULL; - bsr_t = NULL; - bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]; - bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]; - bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]; - bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]; - - LOG_D(MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,subframe, - UE_mac_inst[module_idP].BSR_reporting_active, - UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0], - UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1], - UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2], - UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]); - - } else if (bsr_ce_len == sizeof(BSR_SHORT)) { - bsr_l = NULL; - if ((bsr_t != NULL) && (UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING)) { - //Truncated BSR - bsr_s = NULL; - bsr_t->LCGID = lcg_id_bsr_trunc; - bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc]; - - LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", - module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc); - - } - else - { - bsr_t = NULL; - bsr_s->LCGID = lcg_id_bsr_trunc; - bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc]; - - LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", - module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc); - } - } + if ((padding_len) && (bsr_len == 0)) { + /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */ + if (padding_len >= (1 + BSR_LONG_SIZE)) { + bsr_ce_len = BSR_LONG_SIZE; + bsr_header_len = 1; + // Trigger BSR Padding + UE_mac_inst[module_idP].BSR_reporting_active |= + BSR_TRIGGER_PADDING; + + + } else if (padding_len >= (1 + sizeof(BSR_SHORT))) { + bsr_ce_len = sizeof(BSR_SHORT); + bsr_header_len = 1; + + if (num_lcg_id_with_data > 1) { + // REPORT TRUNCATED BSR + //Get LCGID of highest priority LCID with data + for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { + if (UE_mac_inst[module_idP]. + logicalChannelConfig[lcid] != NULL) { + lcg_id = + UE_mac_inst[module_idP].scheduling_info. + LCGID[lcid]; + + if ((lcg_id < MAX_NUM_LCGID) + && (UE_mac_inst[module_idP]. + scheduling_info.BSR_bytes[lcg_id]) + && + (UE_mac_inst[module_idP].logicalChannelConfig + [lcid]->ul_SpecificParameters->priority <= + highest_priority)) { + highest_priority = + UE_mac_inst[module_idP]. + logicalChannelConfig[lcid]-> + ul_SpecificParameters->priority; + lcg_id_bsr_trunc = lcg_id; + } + } + } + } else { + //Report SHORT BSR, clear bsr_t + bsr_t = NULL; + } + + // Trigger BSR Padding + UE_mac_inst[module_idP].BSR_reporting_active |= + BSR_TRIGGER_PADDING; + } + bsr_len = bsr_header_len + bsr_ce_len; + } + //Fill BSR Infos + if (bsr_ce_len == 0) { + bsr_s = NULL; + bsr_l = NULL; + bsr_t = NULL; + } else if (bsr_ce_len == BSR_LONG_SIZE) { + bsr_s = NULL; + bsr_t = NULL; + bsr_l->Buffer_size0 = + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]; + bsr_l->Buffer_size1 = + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]; + bsr_l->Buffer_size2 = + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]; + bsr_l->Buffer_size3 = + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]; + + LOG_D(MAC, + "[UE %d] Frame %d subframe %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].BSR_reporting_active, + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0], + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1], + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2], + UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]); + + } else if (bsr_ce_len == sizeof(BSR_SHORT)) { + bsr_l = NULL; + if ((bsr_t != NULL) + && (UE_mac_inst[module_idP].BSR_reporting_active & + BSR_TRIGGER_PADDING)) { + //Truncated BSR + bsr_s = NULL; + bsr_t->LCGID = lcg_id_bsr_trunc; + bsr_t->Buffer_size = + UE_mac_inst[module_idP].scheduling_info. + BSR[lcg_id_bsr_trunc]; + + LOG_D(MAC, + "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].BSR_reporting_active, + UE_mac_inst[module_idP]. + scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); + + } else { + bsr_t = NULL; + bsr_s->LCGID = lcg_id_bsr_trunc; + bsr_s->Buffer_size = + UE_mac_inst[module_idP].scheduling_info. + BSR[lcg_id_bsr_trunc]; + + LOG_D(MAC, + "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].BSR_reporting_active, + UE_mac_inst[module_idP]. + scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); + } + } // 1-bit padding or 2-bit padding special padding subheader // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 - if (sdu_length_total) { - padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1); - } - else { - padding_len = buflen - (bsr_len + phr_len); - } - - if (padding_len <= 2) { - short_padding = padding_len; - // only add padding header - post_padding = 0; - //update total MAC Hdr size for RLC data if (sdu_length_total) { - total_rlc_pdu_header_len = total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1; - rlc_pdu_header_len_last = 1; - } - } - else if (sdu_length_total) { - post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); - // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding - if (post_padding == 0) { - total_rlc_pdu_header_len -= rlc_pdu_header_len_last; - padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); - short_padding = padding_len; - total_rlc_pdu_header_len ++; - } - } - else { - if (padding_len == buflen) {// nona mac pdu - *access_mode=CANCELED_ACCESS; - } - - short_padding = 0; - - post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); - } - - // Generate header - // if (num_sdus>0) { - - payload_offset = generate_ulsch_header(ulsch_buffer, // mac header - num_sdus, // num sdus - short_padding, // short pading - sdu_lengths, // sdu length - sdu_lcids, // sdu lcid - phr_p, // power headroom - NULL, // crnti - bsr_t, // truncated bsr - bsr_s, // short bsr - bsr_l, - post_padding); // long_bsr - - LOG_D(MAC, - "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n", - module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, total_rlc_pdu_header_len, - short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset); - // cycle through SDUs and place in ulsch_buffer - if (sdu_length_total) { - memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total); - } - - // fill remainder of DLSCH with random data - if (post_padding) { - for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) { - ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff); - } - } - LOG_D(MAC,"[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", module_idP); - UE_mac_inst[module_idP].scheduling_info.SR_pending=0; - UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0; - - /* Actions when a BSR is sent */ - if (bsr_ce_len) - { - LOG_D(MAC,"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n", - module_idP, bsr_ce_len, bsr_header_len, buflen); - - // Reset ReTx BSR Timer - UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer); - - LOG_D(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n", module_idP, - UE_mac_inst[module_idP].scheduling_info.retxBSR_SF); - - // Reset Periodic Timer except when BSR is truncated - if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity)) - { - UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer); - - LOG_D(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n", - module_idP, UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF); - - } - - // Reset BSR Trigger flags - UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT); + padding_len = + buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - + rlc_pdu_header_len_last + sdu_length_total + 1); + } else { + padding_len = buflen - (bsr_len + phr_len); + } + + if (padding_len <= 2) { + short_padding = padding_len; + // only add padding header + post_padding = 0; + //update total MAC Hdr size for RLC data + if (sdu_length_total) { + total_rlc_pdu_header_len = + total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1; + rlc_pdu_header_len_last = 1; + } + } else if (sdu_length_total) { + post_padding = + buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + + sdu_length_total + 1); + // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding + if (post_padding == 0) { + total_rlc_pdu_header_len -= rlc_pdu_header_len_last; + padding_len = + buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + + sdu_length_total + 1); + short_padding = padding_len; + total_rlc_pdu_header_len++; + } + } else { + if (padding_len == buflen) { // nona mac pdu + *access_mode = CANCELED_ACCESS; + } + + short_padding = 0; + + post_padding = + buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + + sdu_length_total + 1); + } + + // Generate header + // if (num_sdus>0) { + + payload_offset = generate_ulsch_header(ulsch_buffer, // mac header + num_sdus, // num sdus + short_padding, // short pading + sdu_lengths, // sdu length + sdu_lcids, // sdu lcid + phr_p, // power headroom + NULL, // crnti + bsr_t, // truncated bsr + bsr_s, // short bsr + bsr_l, post_padding); // long_bsr + + LOG_D(MAC, + "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n", + module_idP, buflen, sdu_length_total, num_sdus, sdu_lengths[0], + sdu_lcids[0], payload_offset, total_rlc_pdu_header_len, + short_padding, post_padding, bsr_len, phr_len, + buflen - sdu_length_total - payload_offset); + // cycle through SDUs and place in ulsch_buffer + if (sdu_length_total) { + memcpy(&ulsch_buffer[payload_offset], ulsch_buff, + sdu_length_total); + } + // fill remainder of DLSCH with random data + if (post_padding) { + for (j = 0; j < (buflen - sdu_length_total - payload_offset); j++) { + ulsch_buffer[payload_offset + sdu_length_total + j] = + (char) (taus() & 0xff); + } + } + LOG_D(MAC, + "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", + module_idP); + UE_mac_inst[module_idP].scheduling_info.SR_pending = 0; + UE_mac_inst[module_idP].scheduling_info.SR_COUNTER = 0; + + /* Actions when a BSR is sent */ + if (bsr_ce_len) { + LOG_D(MAC, + "[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n", + module_idP, bsr_ce_len, bsr_header_len, buflen); + + // Reset ReTx BSR Timer + UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = + get_sf_retxBSRTimer(UE_mac_inst[module_idP]. + scheduling_info.retxBSR_Timer); + + LOG_D(MAC, "[UE %d] MAC ReTx BSR Timer Reset =%d\n", module_idP, + UE_mac_inst[module_idP].scheduling_info.retxBSR_SF); + + // Reset Periodic Timer except when BSR is truncated + if ((bsr_t == NULL) + && (UE_mac_inst[module_idP].scheduling_info. + periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity)) { + UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = + get_sf_periodicBSRTimer(UE_mac_inst + [module_idP].scheduling_info. + periodicBSR_Timer); + + LOG_D(MAC, "[UE %d] MAC Periodic BSR Timer Reset =%d\n", + module_idP, + UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF); + + } + // Reset BSR Trigger flags + UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); + stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); #endif - - if (opt_enabled) { - trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0); - LOG_D(OPT,"[UE %d][ULSCH] Frame %d subframe %d trace pdu for rnti %x with size %d\n", - module_idP, frameP, subframe, UE_mac_inst[module_idP].crnti, buflen); - } + + if (opt_enabled) { + trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, + UE_mac_inst[module_idP].crnti, + UE_mac_inst[module_idP].txFrame, + UE_mac_inst[module_idP].txSubframe, 0, 0); + LOG_D(OPT, + "[UE %d][ULSCH] Frame %d subframe %d trace pdu for rnti %x with size %d\n", + module_idP, frameP, subframe, UE_mac_inst[module_idP].crnti, + buflen); + } } //------------------------------------------------------------------------------ @@ -1820,281 +2153,327 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid // 4. Perform PHR procedures UE_L2_STATE_t -ue_scheduler( - const module_id_t module_idP, - const frame_t rxFrameP, - const sub_frame_t rxSubframeP, - const frame_t txFrameP, - const sub_frame_t txSubframeP, - const lte_subframe_t directionP, - const uint8_t eNB_indexP, - const int CC_id) +ue_scheduler(const module_id_t module_idP, + const frame_t rxFrameP, + const sub_frame_t rxSubframeP, + const frame_t txFrameP, + const sub_frame_t txSubframeP, + const lte_subframe_t directionP, + const uint8_t eNB_indexP, const int CC_id) //------------------------------------------------------------------------------ { - int lcid; // lcid index - int TTI= 1; - int bucketsizeduration = -1; - int bucketsizeduration_max = -1; - // mac_rlc_status_resp_t rlc_status[MAX_NUM_LCGID]; // 4 - // int8_t lcg_id; - struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL; - protocol_ctxt_t ctxt; + int lcid; // lcid index + int TTI = 1; + int bucketsizeduration = -1; + int bucketsizeduration_max = -1; + // mac_rlc_status_resp_t rlc_status[MAX_NUM_LCGID]; // 4 + // int8_t lcg_id; + struct RACH_ConfigCommon *rach_ConfigCommon = + (struct RACH_ConfigCommon *) NULL; + protocol_ctxt_t ctxt; #if defined(ENABLE_ITTI) - MessageDef *msg_p; - const char *msg_name; - instance_t instance; - int result; + MessageDef *msg_p; + const char *msg_name; + instance_t instance; + int result; #endif #if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].ue_scheduler); + start_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN); - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, txFrameP, txSubframeP,eNB_indexP); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, + UE_mac_inst[module_idP].crnti, txFrameP, + txSubframeP, eNB_indexP); #if defined(ENABLE_ITTI) - do { - // Checks if a message has been sent to MAC sub-task - itti_poll_msg (TASK_MAC_UE, &msg_p); + do { + // Checks if a message has been sent to MAC sub-task + itti_poll_msg(TASK_MAC_UE, &msg_p); - if (msg_p != NULL) { - msg_name = ITTI_MSG_NAME (msg_p); - instance = ITTI_MSG_INSTANCE (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_CCCH_DATA_REQ: - LOG_I(MAC, "Received %s from %s: instance %d, frameP %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); + switch (ITTI_MSG_ID(msg_p)) { + case RRC_MAC_CCCH_DATA_REQ: + LOG_I(MAC, + "Received %s from %s: instance %d, frameP %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; + // TODO process CCCH data req. + break; - default: - LOG_E(MAC, "Received unexpected message %s\n", msg_name); - break; - } + default: + LOG_E(MAC, "Received unexpected message %s\n", msg_name); + break; + } - result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal(result == EXIT_SUCCESS, + "Failed to free memory (%d)!\n", result); + } } - } while(msg_p != NULL); + while (msg_p != NULL); #endif - //Mac_rlc_xface->frameP=frameP; - //Rrc_xface->Frame_index=Mac_rlc_xface->frameP; - //if (subframe%5 == 0) - //LG#ifdef EXMIMO - pdcp_run(&ctxt); - //#endif - UE_mac_inst[module_idP].txFrame = txFrameP; - UE_mac_inst[module_idP].txSubframe = txSubframeP; - UE_mac_inst[module_idP].rxFrame = rxFrameP; - UE_mac_inst[module_idP].rxSubframe = rxSubframeP; + //Mac_rlc_xface->frameP=frameP; + //Rrc_xface->Frame_index=Mac_rlc_xface->frameP; + //if (subframe%5 == 0) + //LG#ifdef EXMIMO + pdcp_run(&ctxt); + //#endif + UE_mac_inst[module_idP].txFrame = txFrameP; + UE_mac_inst[module_idP].txSubframe = txSubframeP; + UE_mac_inst[module_idP].rxFrame = rxFrameP; + UE_mac_inst[module_idP].rxSubframe = rxSubframeP; #ifdef CELLULAR - rrc_rx_tx(module_idP, txFrameP, 0, eNB_indexP); + rrc_rx_tx(module_idP, txFrameP, 0, eNB_indexP); #else - switch (rrc_rx_tx(&ctxt, - eNB_indexP, - CC_id)) { - case RRC_OK: - break; + switch (rrc_rx_tx(&ctxt, eNB_indexP, CC_id)) { + case RRC_OK: + break; - case RRC_ConnSetup_failed: - LOG_E(MAC,"RRCConnectionSetup failed, returning to IDLE state\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + case RRC_ConnSetup_failed: + LOG_E(MAC, "RRCConnectionSetup failed, returning to IDLE state\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - return(CONNECTION_LOST); - break; + return (CONNECTION_LOST); + break; - case RRC_PHY_RESYNCH: - LOG_E(MAC,"RRC Loss of synch, returning PHY_RESYNCH\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + case RRC_PHY_RESYNCH: + LOG_E(MAC, "RRC Loss of synch, returning PHY_RESYNCH\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - return(PHY_RESYNCH); - - case RRC_Handover_failed: - LOG_N(MAC,"Handover failure for UE %d eNB_index %d\n",module_idP,eNB_indexP); - //Invalid...need to add another MAC UE state for re-connection procedure - phy_config_afterHO_ue(module_idP,0,eNB_indexP,(MobilityControlInfo_t *)NULL,1); - //return(3); - break; - - case RRC_HO_STARTED: - LOG_I(MAC,"RRC handover, Instruct PHY to start the contention-free PRACH and synchronization\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + return (PHY_RESYNCH); + + case RRC_Handover_failed: + LOG_N(MAC, "Handover failure for UE %d eNB_index %d\n", module_idP, + eNB_indexP); + //Invalid...need to add another MAC UE state for re-connection procedure + phy_config_afterHO_ue(module_idP, 0, eNB_indexP, + (MobilityControlInfo_t *) NULL, 1); + //return(3); + break; + + case RRC_HO_STARTED: + LOG_I(MAC, + "RRC handover, Instruct PHY to start the contention-free PRACH and synchronization\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - return(PHY_HO_PRACH); + return (PHY_HO_PRACH); - default: - break; - } + default: + break; + } #endif - // Check Contention resolution timer (put in a function later) - if (UE_mac_inst[module_idP].RA_contention_resolution_timer_active == 1) { + // Check Contention resolution timer (put in a function later) + if (UE_mac_inst[module_idP].RA_contention_resolution_timer_active == 1) { - if (UE_mac_inst[module_idP].radioResourceConfigCommon) { - rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon; - } else { - LOG_E(MAC,"FATAL: radioResourceConfigCommon is NULL!!!\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + if (UE_mac_inst[module_idP].radioResourceConfigCommon) { + rach_ConfigCommon = + &UE_mac_inst[module_idP]. + radioResourceConfigCommon->rach_ConfigCommon; + } else { + LOG_E(MAC, "FATAL: radioResourceConfigCommon is NULL!!!\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, + VCD_FUNCTION_OUT); - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); - AssertFatal(1==0,""); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + AssertFatal(1 == 0, ""); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - //return(RRC_OK); - } - - LOG_I(MAC,"Frame %d: Contention resolution timer %d/%ld\n",txFrameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt, - ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3)); - - UE_mac_inst[module_idP].RA_contention_resolution_cnt++; - - if (UE_mac_inst[module_idP].RA_contention_resolution_cnt == - ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3)) { - UE_mac_inst[module_idP].RA_active = 0; - UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0; - // Signal PHY to quit RA procedure - LOG_E(MAC,"Module id %u Contention resolution timer expired, RA failed\n", module_idP); - ra_failed(module_idP,0,eNB_indexP); - } - } - - - // Get RLC status info and update Bj for all lcids that are active - for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++ ) { - if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) { - // meausre the Bj - if ((directionP == SF_UL)&& (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] >= 0)) { - if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters) { - bucketsizeduration = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->prioritisedBitRate * TTI; - bucketsizeduration_max = get_ms_bucketsizeduration(UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->bucketSizeDuration); - } else { - LOG_E(MAC,"[UE %d] lcid %d, NULL ul_SpecificParameters\n",module_idP,lcid); - AssertFatal(1==0,""); - } - - if ( UE_mac_inst[module_idP].scheduling_info.Bj[lcid] > bucketsizeduration_max ) { - UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration_max; - } else { - UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration; - } - } - - - /* - if (lcid == DCCH) { - LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n", - module_idP, txFrameP,txSubframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], -// UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]); - } - */ - } - } - - // Call BSR procedure as described in Section 5.4.5 in 36.321 - - // First check ReTxBSR Timer because it is always configured - // Decrement ReTxBSR Timer if it is running and not null - if ((UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING) - && (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != 0)){ - UE_mac_inst[module_idP].scheduling_info.retxBSR_SF --; - } - - // Decrement Periodic Timer if it is running and not null - if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING) - && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != 0)){ - UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF--; - } - - //Check whether Regular BSR is triggered - if (update_bsr(module_idP,txFrameP, txSubframeP,eNB_indexP) == TRUE) { - // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures - // outlined in Sections 5.4.4 an 5.4.5 of 36.321 - UE_mac_inst[module_idP].scheduling_info.SR_pending= 1; - // Regular BSR trigger - UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_REGULAR; - LOG_D(MAC,"[UE %d][BSR] Regular BSR Triggered Frame %d subframe %d SR for PUSCH is pending\n", - module_idP, txFrameP,txSubframeP); - } - - // UE has no valid phy config dedicated || no valid/released SR - if ((UE_mac_inst[module_idP].physicalConfigDedicated == NULL)) { - // cancel all pending SRs - UE_mac_inst[module_idP].scheduling_info.SR_pending=0; - UE_mac_inst[module_idP].ul_active=0; - LOG_T(MAC,"[UE %d] Release all SRs \n", module_idP); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + //return(RRC_OK); + } + + LOG_I(MAC, "Frame %d: Contention resolution timer %d/%ld\n", + txFrameP, + UE_mac_inst[module_idP].RA_contention_resolution_cnt, + ((1 + + rach_ConfigCommon-> + ra_SupervisionInfo.mac_ContentionResolutionTimer) << 3)); + + UE_mac_inst[module_idP].RA_contention_resolution_cnt++; + + if (UE_mac_inst[module_idP].RA_contention_resolution_cnt == + ((1 + + rach_ConfigCommon-> + ra_SupervisionInfo.mac_ContentionResolutionTimer) << 3)) { + UE_mac_inst[module_idP].RA_active = 0; + UE_mac_inst[module_idP].RA_contention_resolution_timer_active = + 0; + // Signal PHY to quit RA procedure + LOG_E(MAC, + "Module id %u Contention resolution timer expired, RA failed\n", + module_idP); + ra_failed(module_idP, 0, eNB_indexP); + } + } + // Get RLC status info and update Bj for all lcids that are active + for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { + if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) { + // meausre the Bj + if ((directionP == SF_UL) + && (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] >= 0)) { + if (UE_mac_inst[module_idP]. + logicalChannelConfig[lcid]->ul_SpecificParameters) { + bucketsizeduration = + UE_mac_inst[module_idP].logicalChannelConfig + [lcid]->ul_SpecificParameters->prioritisedBitRate * + TTI; + bucketsizeduration_max = + get_ms_bucketsizeduration(UE_mac_inst + [module_idP].logicalChannelConfig + [lcid]->ul_SpecificParameters->bucketSizeDuration); + } else { + LOG_E(MAC, + "[UE %d] lcid %d, NULL ul_SpecificParameters\n", + module_idP, lcid); + AssertFatal(1 == 0, ""); + } + + if (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] > + bucketsizeduration_max) { + UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = + bucketsizeduration_max; + } else { + UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = + bucketsizeduration; + } + } + + + /* + if (lcid == DCCH) { + LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n", + module_idP, txFrameP,txSubframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], + // UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]); + } + */ + } + } + + // Call BSR procedure as described in Section 5.4.5 in 36.321 + + // First check ReTxBSR Timer because it is always configured + // Decrement ReTxBSR Timer if it is running and not null + if ((UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != + MAC_UE_BSR_TIMER_NOT_RUNNING) + && (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != 0)) { + UE_mac_inst[module_idP].scheduling_info.retxBSR_SF--; + } + // Decrement Periodic Timer if it is running and not null + if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != + MAC_UE_BSR_TIMER_NOT_RUNNING) + && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != 0)) { + UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF--; + } + //Check whether Regular BSR is triggered + if (update_bsr(module_idP, txFrameP, txSubframeP, eNB_indexP) == TRUE) { + // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures + // outlined in Sections 5.4.4 an 5.4.5 of 36.321 + UE_mac_inst[module_idP].scheduling_info.SR_pending = 1; + // Regular BSR trigger + UE_mac_inst[module_idP].BSR_reporting_active |= + BSR_TRIGGER_REGULAR; + LOG_D(MAC, + "[UE %d][BSR] Regular BSR Triggered Frame %d subframe %d SR for PUSCH is pending\n", + module_idP, txFrameP, txSubframeP); + } + // UE has no valid phy config dedicated || no valid/released SR + if ((UE_mac_inst[module_idP].physicalConfigDedicated == NULL)) { + // cancel all pending SRs + UE_mac_inst[module_idP].scheduling_info.SR_pending = 0; + UE_mac_inst[module_idP].ul_active = 0; + LOG_T(MAC, "[UE %d] Release all SRs \n", module_idP); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE - stop_meas(&UE_mac_inst[module_idP].ue_scheduler); + stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - return(CONNECTION_OK); - } - - if ((UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig == NULL) || - (UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_release)) { + return (CONNECTION_OK); + } - // initiate RA with CRNTI included in msg3 (no contention) as descibed in 36.321 sec 5.1.5 + if ((UE_mac_inst[module_idP]. + physicalConfigDedicated->schedulingRequestConfig == NULL) + || (UE_mac_inst[module_idP]. + physicalConfigDedicated->schedulingRequestConfig->present == + SchedulingRequestConfig_PR_release)) { - // cancel all pending SRs - UE_mac_inst[module_idP].scheduling_info.SR_pending=0; - UE_mac_inst[module_idP].ul_active=0; - LOG_T(MAC,"[UE %d] Release all SRs \n", module_idP); - } + // initiate RA with CRNTI included in msg3 (no contention) as descibed in 36.321 sec 5.1.5 - // Put this in a function - // Call PHR procedure as described in Section 5.4.6 in 36.321 - if (UE_mac_inst[module_idP].PHR_state == MAC_MainConfig__phr_Config_PR_setup) { // normal operation + // cancel all pending SRs + UE_mac_inst[module_idP].scheduling_info.SR_pending = 0; + UE_mac_inst[module_idP].ul_active = 0; + LOG_T(MAC, "[UE %d] Release all SRs \n", module_idP); + } + // Put this in a function + // Call PHR procedure as described in Section 5.4.6 in 36.321 + if (UE_mac_inst[module_idP].PHR_state == MAC_MainConfig__phr_Config_PR_setup) { // normal operation + + if (UE_mac_inst[module_idP].PHR_reconfigured == 1) { // upon (re)configuration of the power headroom reporting functionality by upper layers + UE_mac_inst[module_idP].PHR_reporting_active = 1; + UE_mac_inst[module_idP].PHR_reconfigured = 0; + } else { + //LOG_D(MAC,"PHR normal operation %d active %d \n", UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].PHR_reporting_active); + if ((UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF <= + 0) + && + ((get_PL(module_idP, 0, eNB_indexP) < + UE_mac_inst[module_idP].scheduling_info. + PathlossChange_db) + || (UE_mac_inst[module_idP].power_backoff_db[eNB_indexP] > + UE_mac_inst[module_idP]. + scheduling_info.PathlossChange_db))) + // trigger PHR and reset the timer later when the PHR report is sent + { + UE_mac_inst[module_idP].PHR_reporting_active = 1; + } else if (UE_mac_inst[module_idP].PHR_reporting_active == 0) { + UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF--; + } + + if (UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF <= + 0) + // trigger PHR and reset the timer later when the PHR report is sent + { + UE_mac_inst[module_idP].PHR_reporting_active = 1; + } else if (UE_mac_inst[module_idP].PHR_reporting_active == 0) { + UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF--; + } + } + } else { // release / nothing + UE_mac_inst[module_idP].PHR_reporting_active = 0; // release PHR + } - if (UE_mac_inst[module_idP].PHR_reconfigured == 1) { // upon (re)configuration of the power headroom reporting functionality by upper layers - UE_mac_inst[module_idP].PHR_reporting_active = 1; - UE_mac_inst[module_idP].PHR_reconfigured = 0; - } else { - //LOG_D(MAC,"PHR normal operation %d active %d \n", UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].PHR_reporting_active); - if ((UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF <= 0) && - ((get_PL(module_idP,0,eNB_indexP) < UE_mac_inst[module_idP].scheduling_info.PathlossChange_db) || - (UE_mac_inst[module_idP].power_backoff_db[eNB_indexP] > UE_mac_inst[module_idP].scheduling_info.PathlossChange_db))) - // trigger PHR and reset the timer later when the PHR report is sent - { - UE_mac_inst[module_idP].PHR_reporting_active = 1; - } else if (UE_mac_inst[module_idP].PHR_reporting_active ==0 ) { - UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF--; - } - - if (UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF <= 0 ) - // trigger PHR and reset the timer later when the PHR report is sent - { - UE_mac_inst[module_idP].PHR_reporting_active = 1; - } else if (UE_mac_inst[module_idP].PHR_reporting_active == 0 ) { - UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF--; - } - } - } else { // release / nothing - UE_mac_inst[module_idP].PHR_reporting_active = 0; // release PHR - } - - //If the UE has UL resources allocated for new transmission for this TTI here: - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); + //If the UE has UL resources allocated for new transmission for this TTI here: + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME + (VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE stop_meas(&UE_mac_inst[module_idP].ue_scheduler); #endif - return(CONNECTION_OK); + return (CONNECTION_OK); } // to be improved @@ -2102,522 +2481,564 @@ ue_scheduler( extern int cba_backoff; double uniform_rngen(int min, int max) { - double random = (double)taus()/((double)0xffffffff); - return (max - min) * random + min; + double random = (double) taus() / ((double) 0xffffffff); + return (max - min) * random + min; } -int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen) +int +cba_access(module_id_t module_idP, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, uint16_t buflen) { - mac_rlc_status_resp_t rlc_status; - int header_offset=4; - int rv =0; - - /* - if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64)) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64)) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) ) - // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive - && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) { // backoff - // LOG_D(MAC,"[UE %d] Frame %d Subframe %d: the current CBA backoff is %d \n", module_idP, frameP, subframe, - // UE_mac_inst[module_idP].cba_last_access[0] ); - - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,40)); - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - - rv=1; - } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 )) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 )) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) ) - // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive - && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){ - - UE_mac_inst[module_idP].cba_last_access[0]-=1; - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: CBA backoff is decreased by one to %d UL active state %d \n", - module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - - } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] == 0 )) && - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] == 0 )) && - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] == 0 )) ) - && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){ - UE_mac_inst[module_idP].cba_last_access[0]-=1; - }*/ - - if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]<64) ) { - return 0; - } - - if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] <= 0 ) && - (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] <= 0 ) && - (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] <= 0 ) ) { - return 0; - } - - if (cba_backoff == 0 ) { // apply probablisitc method - UE_mac_inst[module_idP].cba_last_access[0]= uniform_rngen(0,1); - - if (uniform_rngen(0,1) > 0.6 ) { - LOG_I(MAC,"[UE %d] Frame %d Subframe %d: CBA probability-based backoff (%d), UL active state %d \n", module_idP, frameP, subframe, - cba_backoff,UE_mac_inst[module_idP].ul_active); - - rv=1; - } - } else { - - if (UE_mac_inst[module_idP].cba_last_access[0] <= 0) { - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,cba_backoff)); - - LOG_I(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d/%d UL active state %d \n", module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active); - - rv = 1; - /* - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index - DTCH, - 0); - - if (( - // (rlc_status.pdus_in_buffer > 0 ) && - // (UE_mac_inst[module_idP].ul_active == 0) && // check if the ul is acrtive - (rlc_status.head_sdu_is_segmented == 0 ) && - ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen ) - )){ - rv = 1; - - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30)); - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - */ + mac_rlc_status_resp_t rlc_status; + int header_offset = 4; + int rv = 0; + + /* + if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64)) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64)) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) ) + // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive + && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) { // backoff + // LOG_D(MAC,"[UE %d] Frame %d Subframe %d: the current CBA backoff is %d \n", module_idP, frameP, subframe, + // UE_mac_inst[module_idP].cba_last_access[0] ); + + UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,40)); + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); + + rv=1; + } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 )) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 )) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) ) + // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive + && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){ + + UE_mac_inst[module_idP].cba_last_access[0]-=1; + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: CBA backoff is decreased by one to %d UL active state %d \n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); + + } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] == 0 )) && + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] == 0 )) && + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] == 0 )) ) + && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){ + UE_mac_inst[module_idP].cba_last_access[0]-=1; + } */ + + if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0] > 0) + && (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0] < 64)) { + return 0; + } + + if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] <= 0) && + (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] <= 0) && + (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] <= 0)) { + return 0; + } + + if (cba_backoff == 0) { // apply probablisitc method + UE_mac_inst[module_idP].cba_last_access[0] = uniform_rngen(0, 1); + + if (uniform_rngen(0, 1) > 0.6) { + LOG_I(MAC, + "[UE %d] Frame %d Subframe %d: CBA probability-based backoff (%d), UL active state %d \n", + module_idP, frameP, subframe, cba_backoff, + UE_mac_inst[module_idP].ul_active); + + rv = 1; + } } else { - UE_mac_inst[module_idP].cba_last_access[0]-=1; - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n", - module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - } - } - - return rv; - /* - if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64)) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64)) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) ) - // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive - && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) { - - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,cba_backoff)); - - LOG_I(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d/%d UL active state %d \n", module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active); - - rv = 1; - - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index - DTCH, - 0); - - if (( - // (rlc_status.pdus_in_buffer > 0 ) && - // (UE_mac_inst[module_idP].ul_active == 0) && // check if the ul is acrtive - (rlc_status.head_sdu_is_segmented == 0 ) && - ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen ) - )){ - rv = 1; - - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30)); - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - } else - UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,5)); - - - } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 )) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 )) || - ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) ) - // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive - && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ) - { - - UE_mac_inst[module_idP].cba_last_access[0]-=1; - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n", - module_idP, frameP, subframe, - UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); - } - } - */ + + if (UE_mac_inst[module_idP].cba_last_access[0] <= 0) { + UE_mac_inst[module_idP].cba_last_access[0] = + round(uniform_rngen(1, cba_backoff)); + + LOG_I(MAC, + "[UE %d] Frame %d Subframe %d: start a new CBA backoff %d/%d UL active state %d \n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], cba_backoff, + UE_mac_inst[module_idP].ul_active); + + rv = 1; + /* + rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index + DTCH, + 0); + + if (( + // (rlc_status.pdus_in_buffer > 0 ) && + // (UE_mac_inst[module_idP].ul_active == 0) && // check if the ul is acrtive + (rlc_status.head_sdu_is_segmented == 0 ) && + ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen ) + )){ + rv = 1; + + UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30)); + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); + */ + } else { + UE_mac_inst[module_idP].cba_last_access[0] -= 1; + LOG_D(MAC, + "[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], + UE_mac_inst[module_idP].ul_active); + } + } + + return rv; + /* + if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64)) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64)) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) ) + // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive + && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) { + + UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,cba_backoff)); + + LOG_I(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d/%d UL active state %d \n", module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active); + + rv = 1; + + rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index + DTCH, + 0); + + if (( + // (rlc_status.pdus_in_buffer > 0 ) && + // (UE_mac_inst[module_idP].ul_active == 0) && // check if the ul is acrtive + (rlc_status.head_sdu_is_segmented == 0 ) && + ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen ) + )){ + rv = 1; + + UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30)); + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff %d UL active state %d \n", module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); + } else + UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,5)); + + + } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 )) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 )) || + ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) ) + // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive + && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ) + { + + UE_mac_inst[module_idP].cba_last_access[0]-=1; + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n", + module_idP, frameP, subframe, + UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active); + } + } + */ } #endif -boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index) +boolean_t +update_bsr(module_id_t module_idP, frame_t frameP, + sub_frame_t subframeP, eNB_index_t eNB_index) { - mac_rlc_status_resp_t rlc_status; - boolean_t bsr_regular_triggered = FALSE; - uint8_t lcid; - uint8_t lcgid; - uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined - uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = {0,0,0,0}; - int32_t lcid_bytes_in_buffer[MAX_NUM_LCID]; - /* Array for ordering LCID with data per decreasing priority order */ - uint8_t lcid_reordered_array[MAX_NUM_LCID]= - {MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID}; - uint8_t pos_next = 0; - uint8_t highest_priority = 16; - uint8_t array_index = 0; - - // Reset All BSR Infos - lcid_bytes_in_buffer[0] = 0; - for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++) - { - // Reset transmission status - lcid_bytes_in_buffer[lcid] = 0; - UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY; - } - - for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++) - { - // Reset Buffer Info - UE_mac_inst[module_idP].scheduling_info.BSR[lcgid]=0; - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid]=0; - } - - //Get Buffer Occupancy and fill lcid_reordered_array - for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++) - { - if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) - { - lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]; - - // Store already available data to transmit per Group - if (lcgid < MAX_NUM_LCGID) - { - lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]; - } - - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, - lcid, - 0xFFFF); //TBS is not used in RLC at this step, set a special value for debug - - lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; - - if (rlc_status.bytes_in_buffer > 0) - { - LOG_D(MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n", - module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,subframeP); - - UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY; - //Update BSR_bytes and position in lcid_reordered_array only if Group is defined - if (lcgid < MAX_NUM_LCGID) - { - num_lcid_with_data ++; - // sum lcid buffer which has same lcgid - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer; - - //Fill in the array - array_index = 0; - do - { - if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority) - { - //Insert if priority is higher or equal (lower or equal in value) - for (pos_next=num_lcid_with_data-1; pos_next > array_index; pos_next--) - { - lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1]; - - } - lcid_reordered_array[array_index] = lcid; - break; - - } - array_index ++; - } - while ((array_index < num_lcid_with_data) && (array_index < MAX_NUM_LCID)); - } + mac_rlc_status_resp_t rlc_status; + boolean_t bsr_regular_triggered = FALSE; + uint8_t lcid; + uint8_t lcgid; + uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined + uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = { 0, 0, 0, 0 }; + int32_t lcid_bytes_in_buffer[MAX_NUM_LCID]; + /* Array for ordering LCID with data per decreasing priority order */ + uint8_t lcid_reordered_array[MAX_NUM_LCID] = + { MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, + MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, + MAX_NUM_LCID, + MAX_NUM_LCID, MAX_NUM_LCID + }; + uint8_t pos_next = 0; + uint8_t highest_priority = 16; + uint8_t array_index = 0; + + // Reset All BSR Infos + lcid_bytes_in_buffer[0] = 0; + for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { + // Reset transmission status + lcid_bytes_in_buffer[lcid] = 0; + UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = + LCID_EMPTY; + } + + for (lcgid = 0; lcgid < MAX_NUM_LCGID; lcgid++) { + // Reset Buffer Info + UE_mac_inst[module_idP].scheduling_info.BSR[lcgid] = 0; + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] = 0; + } + + //Get Buffer Occupancy and fill lcid_reordered_array + for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { + if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) { + lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]; + + // Store already available data to transmit per Group + if (lcgid < MAX_NUM_LCGID) { + lcgid_buffer_remain[lcgid] += + UE_mac_inst[module_idP]. + scheduling_info.LCID_buffer_remain[lcid]; + } + + rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index, frameP, subframeP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, 0xFFFF); //TBS is not used in RLC at this step, set a special value for debug + + lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, + "[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n", + module_idP, lcid, lcgid, rlc_status.bytes_in_buffer, + frameP, subframeP); + + UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = + LCID_NOT_EMPTY; + //Update BSR_bytes and position in lcid_reordered_array only if Group is defined + if (lcgid < MAX_NUM_LCGID) { + num_lcid_with_data++; + // sum lcid buffer which has same lcgid + UE_mac_inst[module_idP].scheduling_info. + BSR_bytes[lcgid] += rlc_status.bytes_in_buffer; + + //Fill in the array + array_index = 0; + do { + if (UE_mac_inst[module_idP].logicalChannelConfig + [lcid]->ul_SpecificParameters->priority <= + highest_priority) { + //Insert if priority is higher or equal (lower or equal in value) + for (pos_next = num_lcid_with_data - 1; + pos_next > array_index; pos_next--) { + lcid_reordered_array[pos_next] = + lcid_reordered_array[pos_next - 1]; + + } + lcid_reordered_array[array_index] = lcid; + break; + + } + array_index++; } - } - - } - - // Check whether a regular BSR can be triggered according to the first cases in 36.321 - if (num_lcid_with_data) - { - LOG_D(MAC,"[UE %d] PDCCH Tick at frame %d subframe %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n", - module_idP, frameP, subframeP,num_lcid_with_data,lcid_reordered_array[0],lcid_reordered_array[1],lcid_reordered_array[2]); - - for (array_index=0; array_index < num_lcid_with_data; array_index++) - { - lcid = lcid_reordered_array[array_index]; - /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity - either the data belongs to a logical channel with higher priority than the priorities of the logical channels - which belong to any LCG and for which data is already available for transmission - */ - if ((UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] == 0) - /* or there is no data available for any of the logical channels which belong to a LCG */ - ||(lcgid_buffer_remain[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0) - ) - { - bsr_regular_triggered = TRUE; - - LOG_D(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n", - module_idP, lcid,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],frameP, subframeP); - - break; - } - } - - // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission - if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0) - { - bsr_regular_triggered = TRUE; - - if ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_REGULAR) == 0) { - LOG_I(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d subframe %d\n", - module_idP, frameP, subframeP); - } - - } - } - - //Store Buffer Occupancy in remain buffers for next TTI - for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++) - { - UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_bytes_in_buffer[lcid]; - } - - return bsr_regular_triggered; + while ((array_index < num_lcid_with_data) + && (array_index < MAX_NUM_LCID)); + } + } + } + + } + + // Check whether a regular BSR can be triggered according to the first cases in 36.321 + if (num_lcid_with_data) { + LOG_D(MAC, + "[UE %d] PDCCH Tick at frame %d subframe %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n", + module_idP, frameP, subframeP, num_lcid_with_data, + lcid_reordered_array[0], lcid_reordered_array[1], + lcid_reordered_array[2]); + + for (array_index = 0; array_index < num_lcid_with_data; + array_index++) { + lcid = lcid_reordered_array[array_index]; + /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity + either the data belongs to a logical channel with higher priority than the priorities of the logical channels + which belong to any LCG and for which data is already available for transmission + */ + if ((UE_mac_inst[module_idP]. + scheduling_info.LCID_buffer_remain[lcid] == 0) + /* or there is no data available for any of the logical channels which belong to a LCG */ + || + (lcgid_buffer_remain + [UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == + 0)) { + bsr_regular_triggered = TRUE; + + LOG_D(MAC, + "[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n", + module_idP, lcid, + UE_mac_inst[module_idP].scheduling_info.LCGID[lcid], + frameP, subframeP); + + break; + } + } + + // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission + if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0) { + bsr_regular_triggered = TRUE; + + if ((UE_mac_inst[module_idP].BSR_reporting_active & + BSR_TRIGGER_REGULAR) == 0) { + LOG_I(MAC, + "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d subframe %d\n", + module_idP, frameP, subframeP); + } + + } + } + //Store Buffer Occupancy in remain buffers for next TTI + for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { + UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = + lcid_bytes_in_buffer[lcid]; + } + + return bsr_regular_triggered; } -uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value) +uint8_t +locate_BsrIndexByBufferSize(const uint32_t * table, int size, int value) { - uint8_t ju, jm, jl; - int ascend; + uint8_t ju, jm, jl; + int ascend; - DevAssert( size > 0 ); - DevAssert( size <= 256 ); + DevAssert(size > 0); + DevAssert(size <= 256); - if (value == 0) { - return 0; //elseif (value > 150000) return 63; - } + if (value == 0) { + return 0; //elseif (value > 150000) return 63; + } - jl = 0; // lower bound - ju = size - 1; // upper bound - ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise + jl = 0; // lower bound + ju = size - 1; // upper bound + ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise - while (ju-jl > 1) { //If we are not yet done, - jm = (ju+jl) >> 1; //compute a midpoint, + while (ju - jl > 1) { //If we are not yet done, + jm = (ju + jl) >> 1; //compute a midpoint, - if ((value >= table[jm]) == ascend) { - jl=jm; // replace the lower limit - } else { - ju=jm; //replace the upper limit - } + if ((value >= table[jm]) == ascend) { + jl = jm; // replace the lower limit + } else { + ju = jm; //replace the upper limit + } - LOG_T(MAC,"[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n", jm, table[jm], value); - } + LOG_T(MAC, + "[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n", + jm, table[jm], value); + } - if (value == table[jl]) { - return jl; - } else { - return jl+1; //equally ju - } + if (value == table[jl]) { + return jl; + } else { + return jl + 1; //equally ju + } } int get_sf_periodicBSRTimer(uint8_t sf_offset) { - switch (sf_offset) { - case PeriodicBSR_Timer_r12_sf5: - return 5; - break; + switch (sf_offset) { + case PeriodicBSR_Timer_r12_sf5: + return 5; + break; - case PeriodicBSR_Timer_r12_sf10: - return 10; - break; + case PeriodicBSR_Timer_r12_sf10: + return 10; + break; - case PeriodicBSR_Timer_r12_sf16: - return 16; - break; + case PeriodicBSR_Timer_r12_sf16: + return 16; + break; - case PeriodicBSR_Timer_r12_sf20: - return 20; - break; + case PeriodicBSR_Timer_r12_sf20: + return 20; + break; - case PeriodicBSR_Timer_r12_sf32: - return 32; - break; + case PeriodicBSR_Timer_r12_sf32: + return 32; + break; - case PeriodicBSR_Timer_r12_sf40: - return 40; - break; + case PeriodicBSR_Timer_r12_sf40: + return 40; + break; - case PeriodicBSR_Timer_r12_sf64: - return 64; - break; + case PeriodicBSR_Timer_r12_sf64: + return 64; + break; - case PeriodicBSR_Timer_r12_sf80: - return 80; - break; + case PeriodicBSR_Timer_r12_sf80: + return 80; + break; - case PeriodicBSR_Timer_r12_sf128: - return 128; - break; + case PeriodicBSR_Timer_r12_sf128: + return 128; + break; - case PeriodicBSR_Timer_r12_sf160: - return 160; - break; + case PeriodicBSR_Timer_r12_sf160: + return 160; + break; - case PeriodicBSR_Timer_r12_sf320: - return 320; - break; + case PeriodicBSR_Timer_r12_sf320: + return 320; + break; - case PeriodicBSR_Timer_r12_sf640: - return 640; - break; + case PeriodicBSR_Timer_r12_sf640: + return 640; + break; - case PeriodicBSR_Timer_r12_sf1280: - return 1280; - break; + case PeriodicBSR_Timer_r12_sf1280: + return 1280; + break; - case PeriodicBSR_Timer_r12_sf2560: - return 2560; - break; + case PeriodicBSR_Timer_r12_sf2560: + return 2560; + break; - case PeriodicBSR_Timer_r12_infinity: - default: - return 0xFFFF; - break; - } + case PeriodicBSR_Timer_r12_infinity: + default: + return 0xFFFF; + break; + } } int get_sf_retxBSRTimer(uint8_t sf_offset) { - switch (sf_offset) { - case RetxBSR_Timer_r12_sf320: - return 320; - break; + switch (sf_offset) { + case RetxBSR_Timer_r12_sf320: + return 320; + break; - case RetxBSR_Timer_r12_sf640: - return 640; - break; + case RetxBSR_Timer_r12_sf640: + return 640; + break; - case RetxBSR_Timer_r12_sf1280: - return 1280; - break; + case RetxBSR_Timer_r12_sf1280: + return 1280; + break; - case RetxBSR_Timer_r12_sf2560: - return 2560; - break; + case RetxBSR_Timer_r12_sf2560: + return 2560; + break; - case RetxBSR_Timer_r12_sf5120: - return 5120; - break; + case RetxBSR_Timer_r12_sf5120: + return 5120; + break; - case RetxBSR_Timer_r12_sf10240: - return 10240; - break; + case RetxBSR_Timer_r12_sf10240: + return 10240; + break; - default: - return -1; - break; - } + default: + return -1; + break; + } } + int get_ms_bucketsizeduration(uint8_t bucketsizeduration) { - switch (bucketsizeduration) { - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50: - return 50; - break; - - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100: - return 100; - break; - - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms150: - return 150; - break; - - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms300: - return 300; - break; - - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms500: - return 500; - break; - - case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000: - return 1000; - break; - - default: - return 0; - break; - } + switch (bucketsizeduration) { + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50: + return + 50; + break; + + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100: + return + 100; + break; + + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms150: + return + 150; + break; + + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms300: + return + 300; + break; + + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms500: + return + 500; + break; + + case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000: + return + 1000; + break; + + default: + return 0; + break; + } } -void update_phr(module_id_t module_idP,int CC_id) +void update_phr(module_id_t module_idP, int CC_id) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); - - UE_mac_inst[module_idP].PHR_reporting_active =0; - UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF = get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer); - UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF = get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer); - // LOG_D(MAC,"phr %d %d\n ",UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF); + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + + UE_mac_inst[module_idP].PHR_reporting_active = 0; + UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF = + get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP]. + scheduling_info.periodicPHR_Timer); + UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF = + get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP]. + scheduling_info.prohibitPHR_Timer); + // LOG_D(MAC,"phr %d %d\n ",UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF); } -uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index) + +uint8_t +get_phr_mapping(module_id_t module_idP, int CC_id, uint8_t eNB_index) { - AssertFatal(CC_id==0, - "Transmission on secondary CCs is not supported yet\n"); + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); - //power headroom reporting range is from -23 ...+40 dB, as described in 36313 - //note: mac_xface->get_Po_NOMINAL_PUSCH(module_idP) is float - if (get_PHR(module_idP,CC_id,eNB_index) < -23) { - return 0; - } else if (get_PHR(module_idP,CC_id,eNB_index) >= 40) { - return 63; - } else { // -23 to 40 - return (uint8_t) get_PHR(module_idP,CC_id,eNB_index) + PHR_MAPPING_OFFSET; + //power headroom reporting range is from -23 ...+40 dB, as described in 36313 + //note: mac_xface->get_Po_NOMINAL_PUSCH(module_idP) is float + if (get_PHR(module_idP, CC_id, eNB_index) < -23) { + return 0; + } else if (get_PHR(module_idP, CC_id, eNB_index) >= 40) { + return 63; + } else { // -23 to 40 + return (uint8_t) get_PHR(module_idP, CC_id, + eNB_index) + PHR_MAPPING_OFFSET; - } + } } + int get_sf_perioidicPHR_Timer(uint8_t perioidicPHR_Timer) { - return (perioidicPHR_Timer+1)*10; + return (perioidicPHR_Timer + 1) * 10; } int get_sf_prohibitPHR_Timer(uint8_t prohibitPHR_Timer) { - return (prohibitPHR_Timer)*10; + return (prohibitPHR_Timer) * 10; } int get_db_dl_PathlossChange(uint8_t dl_PathlossChange) { - switch (dl_PathlossChange) { - case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1: - return 1; - break; - - case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3: - return 3; - break; - - case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB6: - return 6; - break; - - case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_infinity: - default: - return -1; - break; - } + switch (dl_PathlossChange) { + case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1: + return 1; + break; + + case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3: + return 3; + break; + + case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB6: + return 6; + break; + + case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_infinity: + default: + return -1; + break; + } } diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h index 4ff54752530fe9e892d8bf93f355effd03d12c89..238608816121c5e438f0089a8bd8d96df9191113 100644 --- a/openair2/LAYER2/MAC/vars.h +++ b/openair2/LAYER2/MAC/vars.h @@ -34,25 +34,32 @@ #define __MAC_VARS_H__ #ifdef USER_MODE //#include "stdio.h" -#endif //USER_MODE +#endif //USER_MODE #include "PHY/defs.h" #include "defs.h" #include "COMMON/mac_rrc_primitives.h" -const uint32_t BSR_TABLE[BSR_TABLE_SIZE]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91, - 105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132, - 1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099, - 16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439, 128125,150000, 300000 - }; -// extended bsr table--currently not used -const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE] = {0,10,13,16,19,23,29,35,43,53,65,80,98,120,147, - 181,223,274,337,414,509,625,769,945,1162,1429, - 1757,2161,2657,3267,4017,4940,6074,7469,9185, - 11294,13888,17077,20999,25822,31752,39045,48012, - 59039,72598,89272,109774,134986,165989,204111, - 250990,308634,379519,466683,573866,705666,867737, - 1067031,1312097,1613447,1984009,2439678,3000000, - 6000000}; +const uint32_t BSR_TABLE[BSR_TABLE_SIZE] = + { 0, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, + 105, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, + 967, 1132, + 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4677, 5467, 6411, 7505, + 8787, 10287, 12043, 14099, + 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255, 68201, + 79846, 93479, 109439, 128125, 150000, 300000 +}; + +// extended bsr table--currently not used +const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE] = + { 0, 10, 13, 16, 19, 23, 29, 35, 43, 53, 65, 80, 98, 120, 147, + 181, 223, 274, 337, 414, 509, 625, 769, 945, 1162, 1429, + 1757, 2161, 2657, 3267, 4017, 4940, 6074, 7469, 9185, + 11294, 13888, 17077, 20999, 25822, 31752, 39045, 48012, + 59039, 72598, 89272, 109774, 134986, 165989, 204111, + 250990, 308634, 379519, 466683, 573866, 705666, 867737, + 1067031, 1312097, 1613447, 1984009, 2439678, 3000000, + 6000000 +}; //#define MAX_SIZE_OF_AGG3 576 //#define MAX_SIZE_OF_AGG2 288 @@ -64,24 +71,26 @@ const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE] = {0,10,13,16,19,23,29,35,43,5 * this is also dependent to transmission mode, where an offset could be defined */ // the follwoing three tables are calibrated for TXMODE 1 and 2 -const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]= { - {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size= 37 bits - //{3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 41 - {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 41 - {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE = 43 - {3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0} // 20_DCI0_CRC_SIZE = 44 +const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE] = { + {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size= 37 bits + //{3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 41 + {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 41 + {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE = 43 + {3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0} // 20_DCI0_CRC_SIZE = 44 }; -const uint8_t cqi2fmt1x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]= { - {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size < 38 bits - {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE < 43 - {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE < 47 - {3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0} // 20_DCI0_CRC_SIZE < 55 + +const uint8_t cqi2fmt1x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE] = { + {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size < 38 bits + {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE < 43 + {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE < 47 + {3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0} // 20_DCI0_CRC_SIZE < 55 }; -const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]= { - {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size= 47 bits - {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 55 - {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE = 59 - {3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0} // 20_DCI0_CRC_SIZE = 64 + +const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE] = { + {3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, // 1.4_DCI0_CRC_Size= 47 bits + {3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, // 5_DCI0_CRC_SIZE = 55 + {3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 10_DCI0_CRC_SIZE = 59 + {3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0} // 20_DCI0_CRC_SIZE = 64 }; //uint32_t EBSR_Level[63]={0,10,13,16,19,23,29,35,43,53,65,80,98,120,147,181}; @@ -89,7 +98,7 @@ const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]= { uint32_t RRC_CONNECTION_FLAG; -UE_MAC_INST *UE_mac_inst; //[NB_MODULE_MAX]; +UE_MAC_INST *UE_mac_inst; //[NB_MODULE_MAX]; MAC_RLC_XFACE *Mac_rlc_xface; /// Primary component carrier index of eNB @@ -97,39 +106,39 @@ int pCC_id[NUMBER_OF_eNB_MAX]; -eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 -eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 +eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 +eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8 #ifdef OPENAIR2 -unsigned char NB_eNB_INST=0; -unsigned char NB_UE_INST=0; -unsigned char NB_RN_INST=0; -unsigned char NB_INST=0; +unsigned char NB_eNB_INST = 0; +unsigned char NB_UE_INST = 0; +unsigned char NB_RN_INST = 0; +unsigned char NB_INST = 0; #endif -DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; +DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; -DCI1A_5MHz_TDD_1_6_t DLSCH_alloc_pdu1A; -DCI1A_5MHz_TDD_1_6_t RA_alloc_pdu; -DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; +DCI1A_5MHz_TDD_1_6_t DLSCH_alloc_pdu1A; +DCI1A_5MHz_TDD_1_6_t RA_alloc_pdu; +DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; -DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; -DCI1_5MHz_TDD_t DLSCH_alloc_pdu; +DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; +DCI1_5MHz_TDD_t DLSCH_alloc_pdu; #if defined(Rel10) || defined(Rel14) -DCI1C_5MHz_t MCCH_alloc_pdu; +DCI1C_5MHz_t MCCH_alloc_pdu; #endif -DCI0_5MHz_FDD_t UL_alloc_pdu_fdd; +DCI0_5MHz_FDD_t UL_alloc_pdu_fdd; -DCI1A_5MHz_FDD_t DLSCH_alloc_pdu1A_fdd; -DCI1A_5MHz_FDD_t RA_alloc_pdu_fdd; -DCI1A_5MHz_FDD_t BCCH_alloc_pdu_fdd; +DCI1A_5MHz_FDD_t DLSCH_alloc_pdu1A_fdd; +DCI1A_5MHz_FDD_t RA_alloc_pdu_fdd; +DCI1A_5MHz_FDD_t BCCH_alloc_pdu_fdd; -DCI1A_5MHz_FDD_t CCCH_alloc_pdu_fdd; -DCI1_5MHz_FDD_t DLSCH_alloc_pdu_fdd; +DCI1A_5MHz_FDD_t CCCH_alloc_pdu_fdd; +DCI1_5MHz_FDD_t DLSCH_alloc_pdu_fdd; DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1; DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; @@ -137,5 +146,3 @@ DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; #endif - - diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index e323a9d5bca71f6c57fd7716b44d9233a7d8c484..ad5bbda3fe77e37982564880d265cd858d307a83 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -235,7 +235,8 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else if (flags == IF4p5_PULTICK) { packet_size = UDP_IF4p5_PULTICK_SIZE_BYTES; - } else if (flags == IF4p5_PRACH) { + } else if ((flags >= IF4p5_PRACH)&& + (flags <= (IF4p5_PRACH+4))) { packet_size = UDP_IF4p5_PRACH_SIZE_BYTES; } else { printf("trx_eth_write_udp_IF4p5: unknown flags %d\n",flags); diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h index 38635712734fa6d21a20078d03899f3b9c8393d6..47ba171f1b9805973d2076629037bb9e920d22c9 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.h @@ -47,7 +47,7 @@ typedef struct { } iqrec_t; #define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz) #define DEF_SF_FILE "/home/nokia/iqfile" // default subframes file name -#define DEF_SF_DELAY_READ 860 // default read delay µs (860=real) +#define DEF_SF_DELAY_READ 400 // default read delay µs (860=real) #define DEF_SF_DELAY_WRITE 15 // default write delay µs (15=real) #define DEF_SF_NB_LOOP 5 // default nb loops diff --git a/targets/DOCS/oai_L1_L2_procedures.ipe b/targets/DOCS/oai_L1_L2_procedures.ipe new file mode 100755 index 0000000000000000000000000000000000000000..2062240c14ad8249bcfa0bf34f04ced87c2f8c61 --- /dev/null +++ b/targets/DOCS/oai_L1_L2_procedures.ipe @@ -0,0 +1,12461 @@ +<?xml version="1.0"?> +<!DOCTYPE ipe SYSTEM "ipe.dtd"> +<ipe version="70107" creator="Ipe 7.2.5"> +<info created="D:20160514115229" modified="D:20171018195314"/> +<preamble>\usepackage{setspace}\usepackage{amsmath}\usepackage{stackrel}</preamble> +<bitmap id="1" width="418" height="289" length="22283" ColorSpace="DeviceRGB" Filter="FlateDecode" BitsPerComponent="8" encoding="base64"> +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 +2NraK/l2+fJVply/fvPGjVufKLfxKb6yX+Xq1ev46b8t2KodLrbDcuXK51Z4+crVm7duPXh4 +7/6DPZSH9xDZS5eu4Of09C4rWceT+zqhGuuIcl9EuZ6eHqIcUe4zWlpaqqmptbGxVdDs9hfB +4QMirh1w2fcfBXxAns8UXd3LF3UuXby4h6JzCVhTjRvDukt6V1w8LYWd2bMygXLY9B32L6ft +lEPt3nv/cjh0+/r6tDoOjo7O36p/uSNCORwhr169vX//IbzZl/KNyt4LWIc09sxpHScPi0Fp +JTNI4k76Ci4pLX327IW9g6MjaoIWFjs7B3lfwY177SvY3d3D0NBYS4PwPg7yvoKbiXJfVWtr +a2VlZfr6hshV4ei2WzUkkp8pB2/k9j1j/XaIuwK+Xbiga2z2Nr8ianSxVqK49rqT0W36+vuF +IlEDh9PA4Wpn4TQ1N+99oKvOri4Ol6u1QfhkHIhyX0Orq6slJaXv3qmz7vr1W3fu3MXMjxZQ +br/yR6xn5+fu/nYx7MKtW3d2UrAXOhf0Tp2SXxf4TDlzek8Fa9DR0VOyV8G3Cxd19Cxs3lVw +E6SbvAWZUHl7yQ7H8ELrr+1lX0ZnPpRxIMp9TdatFRUVIYdlWIc0Ni8vTyKRjH9MExMT+Dc6 +0ZruWd3d3XgRiUQ8Hv8zEgiE8fEJDg5OmOB/dkEOh1teXrGTEhIcbutoWlgek1UU9tGSXRKW +lB0QleQdk7z7kpjhb2Khf+GCHuPfQDxLW8NqYfKMjC/n2187fdo55UbEYu0t+0U5rQ7Cp+JA +lPvaWllZhq/T1ze4d+9hTU2Npt3rwjyDs28rFLZEJ/nIZN2LMtEnSiNeF/ZWZLL20BjPH/9z +Qkfn0nu+bfHnVfzbLkad5vEF1fh7amu1sVRX14gaG1GX956x1tTWaWkQPhMHotxBsW4lKyur +ublFo7ZKS599mJcJgiLc9A1fMP7tU3zb+UiFpWVlL1++cnZ2dXV108bi5OT8+vXb7SP0fenV +B09PlomJqZYG4X0c3rxtam454lcfmE4SVN8yczY2NpaWliHmqZMjIi2lHJjWO1mG18/z7Yvu +JAkLC6c7SWxsbHfXHzvdSaJRlBsaGjYyMhofn2DepqVlNDQ0zM/PGxqaID5oCxwcHNva2ohy +mkw55nDaYafrdFcwPftwFCi3vr7OPEEMn4Y9vnbthouLG/NRaGh4SUnp2NiYmZnlikLt7R3G +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 +QvYK19Ha2tbxQci8mLHPoPX19fb2dqSrCwsLdF7uU0JwEDTVTsCQ2iOSaFC6u7sRQCawbW1t +fX39ym6I+vsHmptbhodH6LwciShHT3jRE15EORJRjihHlCPKkQ4B5QQCofbGUyqd0diel4KC +grX7WK2rJ8qRDgHlPDxZ6ekZvVorDodraWk9NDysaZTLLyh0dnbt1WYlJaWwvX2IciStphwO +YDbbW1//HRydlhYrKxtTU3P54IkaRrnSsvI//nji5uahvbF980bfzz+AKEc6BBmrUCjS3njO +zMxSxvqV1NDAoYyVRFcf6OoDXX0gypGIckQ5ohxRjihHlCPKEeVIRDnNpFx+fr6bm3t8fAJz +7/3w8LC3t4+XF7urq5tZYG1tLSwsPDIySrVr9I2NjdLSMjc3DxbLa499oB1WynV2diKMCKZY +LJYpekGPi4tHqAsKCpXLlJdXuLq6qfVB2tnZ5efnj/lpaenKTtSJciSi3K53x9ra5l//+vel +S1eYvkcyM7O+++77H374qazsfRdAra1tP//8y/HjJ7u733NveXnZzs7+xx9/vnbthp7e5Z9/ +/hUY/NTwEEeWcsXFxQjj99//mJubJ1P096Kjo/vPf35na2uvbCmePn32X//135GR0cpv5ebm +njhx6sKFi4gtwv7y5WvlU3VEORJRbndydHS6fv3mo0eP6+vlD92zWOxHj/5ALUMFYRZgs33e +vjX4/fdHkZGRzJyUlFTU3+TklNXV1dnZWUtL66dPn++6x7nDSrny8nKE8fHjJz4+vnhbXV39 +22+PwC5nZ1dmAYFAcP/+QwsLy2fPnjNP5Q8ODp09e97ExGxiYhKxRYujq6u3F6tMlCMR5WSK +fs9QEx0cnMLDI5C0GhgYMp1qMpRbXFy8fftuRUVlaGgYquTa2jpmYhmmDw1GqI9wd5Sxqglm +GGH09vY1MjLB26CgYEdHZ4QazQqzgIeHJ3xda2vrmTPnmHuBgLVjx35taWlVrmSPo6QR5UhE +OQi554sXL2HPYMl6e/tev36TlyfvIpihXG1t3Y0btzAxMDBw5sz5pqZmTD979oKpuXT14fOU +gzHLzy949ep1X1+fubllamrakyfPGMqhXbh7935lZRWmYZ7ZbG9MxMXFnzt3YXh4iK4+kIhy ++0s5VD3g6+XL1yEhoQ4Ojo2NTSdPnkGGhU+RXiHtCggI9PJinzx5OiwsHDPfvTN6+PB35Rq6 +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 +</bitmap> +<bitmap id="2" width="325" height="558" length="35723" ColorSpace="DeviceRGB" Filter="FlateDecode" BitsPerComponent="8" encoding="base64"> +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 +WVvbOqT0tGQLcir6RFEnwq2VTSIyOl4+u61mb1M+TGe/e/P8We9s8gLiB0znm2ZmUSw637nq +ImifRx3UBXmbWeayf1Gx8Lq1ZX4fdVByyVnLPW2OUsHRfoFBt6kzbbd81a2vjM70uMhZ5va8 +pG8M89XXo/MQ/FiM3VU6oex7o7CioqLl2ezi4G01TXklPZfk7HQ3C2VJhoZvTMPMk2pVXU1F +RRlFQ6/4K0EKEiqR5X3r7yqsDjppmDiEZVXV3iu6GmRpENXWnK8oYZNaXlnXUBdqbO4Xc295 +uMLAw7V6hM5+LztI7EIBofMHTOd0Y+OIjHbqaLqnzl1VU89YT87YMaV5dH3tfNVcN+EufTjd +ZCipHFnzuDM2wMMthebsy8fe6op2yfUtmSHGJsZWVoYyOlZx94aITH8CJu4pHOGW1DS1srK6 +VNQ10Z56UsWr88XwNQ2t88mtC1MdburmSbeuC2s61zzpC2KoeCW29Rb5qfnFravttSEXZQWG +mrEm4/C2/SqVoyurD/MEOEQNLA25937KaxBLL3wG83Xd3WrH6OyNeRdFA/MJnT9crE4MDo5M +rttvC8Od+dk59wa/+8XXqdFHA+Oz65qkp/fh0OTc2POnQxNs7TD5/GHLAJV5paexNCsr+97D +MSLQn4bhalVu+8rhDWnfTxJwT5xYGQoU0ouvocS+EG1nEBoXregT+2RlNEbB5WbN9FhDuNKF +uEl2B6z2Oeiez+mhDvq9dfWiyoeWe/LV9RKohdJ4bayulnvTONVt1drmtkXPWMZ2ipuwP6Ez +AcHPROcK6cPnMtrX/6FmsjHuhEX40NpKU6KPtr6pm62NkWFM691UfuvQ/sWn4QybpIqJ5zUX +pHyubtC511LJ/iprOhgsChWTdiq+k6qkHDJIM3Y21kpT2fnmC+Zs7sXzpob2fn4uelrn4uoH +idQJCH4WLI7fq2h9PvOS/W156klV+0OWqbR0vyQ5Mupm98QKc3G4pv3h3OriQH3n0Pjy4kT/ +vZ5Hy+vG9mxH04NH4yw/x8pkS13Ng4cDzc2D86yri8MPqutaaNNqbepuxvWIiKg7TWQpREBA +QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA +QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA +QEBAQEBA8K6xOPWsvrI0P+cV8hu7R8af9d69P7j0Mzzu2YN66hl1D8f+TJ6x4aHnL5Z/4OLK +8EBHxZ0idl0LbtePLq5fmH7aU9PYv/DmDTND9xrujyysvXHhRefdxocj8z+1CQsTQ02VZRsS +y73bMcw6vfysd+D5xMJ/i5RWXwxVFuRWdQ6t/rj8a2sLkzMLtHAGex6OvPjxD5oZ6qstK8nd +6Pvi+s7XO325/34FLefy1tnvVeXl6N07BdSlu22P31Lu0lR7Q3Vx/kbBeWUD4+wOXR1/0l1R +WvxqtFU09G8qeLm7sZJ+XFn98ze65eWL4Y6Ovsmltbe3ZHluZm5+5Uc0ebS/MS+ndGB04YOk +c3uy88cf7VExNNuATWzBg4H2spi0urn/5kcttRVEmhubmpmZ6hk4xKY1L76Vy00pDEW5S3fH +f6CQcR9Frm0HRdbramZuaH3hTtckdeFp653opKo3h/LqcEt8QlrX1BvMWB7Jj0ms6Zn8qc1o +izH97Pe7lY3W5aWjdC74ZsMqczxQQi8w+cF/xwz7LNxAU1rFODSv6eWPY3NNrI9H3D1qprmk +K6gaWf2jn7SWbSP6h52cBht9r6iseM4vZ5TFvJXR9qBAH1sne+q8uZGFkUtgSe80+7ah+qIg +S2dre1vqkpWZpa1X6uPXx8rig5tHtm3nV1ov2ERTVVHXNr97ihoDkQZCH+/hNV5/oKm6rLzd +1WK63KXnWYHuFlZ0mdZOzg6Wnrn3Hm0uc6Q8eP8BqVsDb53nl0tCfX3jG/5igyc7cxWlZPWt +Aqp7pj5IOt+PdTjEY/P0exRYXlpYXGbPg2MDDxqbHoy/mB0fn1p4uTo/OTo8/oJ1aW1ucmxk +YnZ5cW5qYmL0SW9TW9cUPT+uPepubWxsH3+drmtjTTbatllddMfPlF3i5lErG3ltpl1ZmLqX +k3rjqqeAkGhYA4tlL+cGunqeTW8uaMRDTljBp+xVP+YHmpyS9+x6wVxbWV5cWlmam3o2PbdR +7urU6OT07MLS0hJr3l4b6W1vbGx8+GyWfZVu5Aq7KbN9bY2NzRvKfXludPLFwsJMX3vT/Y7H +37NSmiPPHRQyH9r4+qIu4tA3UrltnWFKJsEpbDqvPOunH/TgKWvMrC2NT07PLc4/6W5pbO59 +8arRi+OdTY2NLT0vNpN2Zf5heRT3jjOBOd1sRTTe39nYeP/xNFvzrM5OTExNjvZ2NHc+mVhb +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 +PaVWFiaWjlQVPd3tHXTM7RLqn7DvbM+OMVY3t/P2pi652VrpmoY2P39tG2OuJeHwl7yxTa90 +2WpJgN5ODt2mobEIbREunZhXps3Ks0rJg0e0wqpezvXdcLezd/TwovvV28neIaGi57WNqrLA +r7+RLJxcqXCX2CvmyO6Pu8HW/EKeVP2bIjz5ebWii7sf1SabGJtRytTJysrY9nzj09lib/V9 +gq7s/HXX7fYLnx+jlgbl12V5FS09PcMjo40luHZwulKKoLkgQlXLjBpa+poGPmEVL5nz+VG+ +eka2VI3szIyNLuaMvFzb4nSeGequrO148brTY+JxV+39gcXFuZnpiY768sys8rbbMVJGHndZ +bpnpwab46zF5Ne1DfX3tHU9mJx7VVt8bfrXOeTlWmpMUExNX/fDNveOVB7WFMTExaRWdyz+4 +6zre0tAwwN5lWRytzC1sfrLZsns50FaTnhwfw0JiWvnwwtvCSBZH6+91snfKWGEkzWNUeS/H +y7KoisXklLezhtPsqzCStamB/OSYmNjCx9OsuXh+pL6q/iH7/uWptob6/onvbOuZR+2VdW0v +vu8mWuxvbHv4jCb5xEDjjesx8fnVz8dGuvp6RmemOurrO5+wVdVCT3N9B2unbKq7PoWqTVxK +49Dru+UL4y01TU+n2RJaaCm4SdWsrIsdePPy4f2ae93P3tjSHytPTi2q6uh90Nz2mG3YLA/c +b+roZ9+13FaTRze8off1RdXa8wf3aloebnZKj/U2FZS1rZtULyfrC1KpG+NvVX4v7OLlRE9G +cix1qaC6c+ktoTvPaqsans5sKnhppKq0rHt0+knn/fr218JjnnXWFtc9YGVd6qgouE4VmpLV +8fz7UQlLEwNV1ffHXq5N9N2vbuphP3RqsLuhsY8+XhouyEjOrKPtvRcPm1OvxVzbGBsjva3V +7DxU/iF6kLCLHmospZ5183brxOTz5uYB9vT8vKmMen7GvVdr5JW+u7To8qu7VpnvN+b6yy30 +bC5fTUlPTwxwdAlPurvEJCAgeE+xNtJZdeW8j4+Pf3pdPxEHAQEBAQEBAQEBAQEBAQEBAQEB +AQEBAQEBAQEBAQEBAQEBAQEBAQEBARv/PyjEf5A= +</bitmap> +<bitmap id="3" width="723" height="430" length="111248" ColorSpace="DeviceRGB" Filter="FlateDecode" BitsPerComponent="8" encoding="base64"> +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 +wJn/A5vjFyA= +</bitmap> +<ipestyle name="basic"> +<symbol name="arrow/arc(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/farc(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/ptarc(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/fptarc(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="mark/circle(sx)" transformations="translations"> +<path fill="sym-stroke"> +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e +</path> +</symbol> +<symbol name="mark/disk(sx)" transformations="translations"> +<path fill="sym-stroke"> +0.6 0 0 0.6 0 0 e +</path> +</symbol> +<symbol name="mark/fdisk(sfx)" transformations="translations"> +<group> +<path fill="sym-fill"> +0.5 0 0 0.5 0 0 e +</path> +<path fill="sym-stroke" fillrule="eofill"> +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e +</path> +</group> +</symbol> +<symbol name="mark/box(sx)" transformations="translations"> +<path fill="sym-stroke" fillrule="eofill"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h +</path> +</symbol> +<symbol name="mark/square(sx)" transformations="translations"> +<path fill="sym-stroke"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +</path> +</symbol> +<symbol name="mark/fsquare(sfx)" transformations="translations"> +<group> +<path fill="sym-fill"> +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h +</path> +<path fill="sym-stroke" fillrule="eofill"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h +</path> +</group> +</symbol> +<symbol name="mark/cross(sx)" transformations="translations"> +<group> +<path fill="sym-stroke"> +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h +</path> +<path fill="sym-stroke"> +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h +</path> +</group> +</symbol> +<symbol name="arrow/fnormal(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/pointed(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/fpointed(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/linear(spx)"> +<path stroke="sym-stroke" pen="sym-pen"> +-1 0.333 m +0 0 l +-1 -0.333 l +</path> +</symbol> +<symbol name="arrow/fdouble(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/double(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h +</path> +</symbol> +<pen name="heavier" value="0.8"/> +<pen name="fat" value="1.2"/> +<pen name="ultrafat" value="2"/> +<symbolsize name="large" value="5"/> +<symbolsize name="small" value="2"/> +<symbolsize name="tiny" value="1.1"/> +<arrowsize name="large" value="10"/> +<arrowsize name="small" value="5"/> +<arrowsize name="tiny" value="3"/> +<color name="red" value="1 0 0"/> +<color name="green" value="0 1 0"/> +<color name="blue" value="0 0 1"/> +<color name="yellow" value="1 1 0"/> +<color name="orange" value="1 0.647 0"/> +<color name="gold" value="1 0.843 0"/> +<color name="purple" value="0.627 0.125 0.941"/> +<color name="gray" value="0.745"/> +<color name="brown" value="0.647 0.165 0.165"/> +<color name="navy" value="0 0 0.502"/> +<color name="pink" value="1 0.753 0.796"/> +<color name="seagreen" value="0.18 0.545 0.341"/> +<color name="turquoise" value="0.251 0.878 0.816"/> +<color name="violet" value="0.933 0.51 0.933"/> +<color name="darkblue" value="0 0 0.545"/> +<color name="darkcyan" value="0 0.545 0.545"/> +<color name="darkgray" value="0.663"/> +<color name="darkgreen" value="0 0.392 0"/> +<color name="darkmagenta" value="0.545 0 0.545"/> +<color name="darkorange" value="1 0.549 0"/> +<color name="darkred" value="0.545 0 0"/> +<color name="lightblue" value="0.678 0.847 0.902"/> +<color name="lightcyan" value="0.878 1 1"/> +<color name="lightgray" value="0.827"/> +<color name="lightgreen" value="0.565 0.933 0.565"/> +<color name="lightyellow" value="1 1 0.878"/> +<dashstyle name="dashed" value="[4] 0"/> +<dashstyle name="dotted" value="[1 3] 0"/> +<dashstyle name="dash dotted" value="[4 2 1 2] 0"/> +<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/> +<textsize name="large" value="\large"/> +<textsize name="Large" value="\Large"/> +<textsize name="LARGE" value="\LARGE"/> +<textsize name="huge" value="\huge"/> +<textsize name="Huge" value="\Huge"/> +<textsize name="small" value="\small"/> +<textsize name="footnote" value="\footnotesize"/> +<textsize name="tiny" value="\tiny"/> +<textstyle name="center" begin="\begin{center}" end="\end{center}"/> +<textstyle name="itemize" begin="\begin{itemize}" end="\end{itemize}"/> +<textstyle name="item" begin="\begin{itemize}\item{}" end="\end{itemize}"/> +<gridsize name="4 pts" value="4"/> +<gridsize name="8 pts (~3 mm)" value="8"/> +<gridsize name="16 pts (~6 mm)" value="16"/> +<gridsize name="32 pts (~12 mm)" value="32"/> +<gridsize name="10 pts (~3.5 mm)" value="10"/> +<gridsize name="20 pts (~7 mm)" value="20"/> +<gridsize name="14 pts (~5 mm)" value="14"/> +<gridsize name="28 pts (~10 mm)" value="28"/> +<gridsize name="56 pts (~20 mm)" value="56"/> +<anglesize name="90 deg" value="90"/> +<anglesize name="60 deg" value="60"/> +<anglesize name="45 deg" value="45"/> +<anglesize name="30 deg" value="30"/> +<anglesize name="22.5 deg" value="22.5"/> +<tiling name="falling" angle="-60" step="4" width="1"/> +<tiling name="rising" angle="30" step="4" width="1"/> +</ipestyle> +<ipestyle name="presentation"> +<symbol name="arrow/arc(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/farc(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="mark/circle(sx)" transformations="translations"> +<path fill="sym-stroke"> +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e +</path> +</symbol> +<symbol name="mark/disk(sx)" transformations="translations"> +<path fill="sym-stroke"> +0.6 0 0 0.6 0 0 e +</path> +</symbol> +<symbol name="mark/fdisk(sfx)" transformations="translations"> +<group> +<path fill="sym-fill"> +0.5 0 0 0.5 0 0 e +</path> +<path fill="sym-stroke" fillrule="eofill"> +0.6 0 0 0.6 0 0 e +0.4 0 0 0.4 0 0 e +</path> +</group> +</symbol> +<symbol name="mark/box(sx)" transformations="translations"> +<path fill="sym-stroke" fillrule="eofill"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h +</path> +</symbol> +<symbol name="mark/square(sx)" transformations="translations"> +<path fill="sym-stroke"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +</path> +</symbol> +<symbol name="mark/fsquare(sfx)" transformations="translations"> +<group> +<path fill="sym-fill"> +-0.5 -0.5 m +0.5 -0.5 l +0.5 0.5 l +-0.5 0.5 l +h +</path> +<path fill="sym-stroke" fillrule="eofill"> +-0.6 -0.6 m +0.6 -0.6 l +0.6 0.6 l +-0.6 0.6 l +h +-0.4 -0.4 m +0.4 -0.4 l +0.4 0.4 l +-0.4 0.4 l +h +</path> +</group> +</symbol> +<symbol name="mark/cross(sx)" transformations="translations"> +<group> +<path fill="sym-stroke"> +-0.43 -0.57 m +0.57 0.43 l +0.43 0.57 l +-0.57 -0.43 l +h +</path> +<path fill="sym-stroke"> +-0.43 0.57 m +0.57 -0.43 l +0.43 -0.57 l +-0.57 0.43 l +h +</path> +</group> +</symbol> +<symbol name="arrow/fnormal(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/pointed(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/fpointed(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-0.8 0 l +-1 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/linear(spx)"> +<path stroke="sym-stroke" pen="sym-pen"> +-1 0.333 m +0 0 l +-1 -0.333 l +</path> +</symbol> +<symbol name="arrow/fdouble(spx)"> +<path stroke="sym-stroke" fill="white" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h +</path> +</symbol> +<symbol name="arrow/double(spx)"> +<path stroke="sym-stroke" fill="sym-stroke" pen="sym-pen"> +0 0 m +-1 0.333 l +-1 -0.333 l +h +-1 0 m +-2 0.333 l +-2 -0.333 l +h +</path> +</symbol> +<pen name="normal" value="1.2"/> +<pen name="heavier" value="2.4"/> +<pen name="fat" value="3.6"/> +<pen name="ultrafat" value="6"/> +<symbolsize name="normal" value="9"/> +<symbolsize name="large" value="15"/> +<symbolsize name="small" value="6"/> +<symbolsize name="tiny" value="3.3"/> +<arrowsize name="normal" value="15"/> +<arrowsize name="large" value="20"/> +<arrowsize name="small" value="10"/> +<arrowsize name="tiny" value="6"/> +<color name="red" value="1 0 0"/> +<color name="green" value="0 1 0"/> +<color name="blue" value="0 0 1"/> +<color name="yellow" value="1 1 0"/> +<color name="orange" value="1 0.647 0"/> +<color name="gold" value="1 0.843 0"/> +<color name="purple" value="0.627 0.125 0.941"/> +<color name="gray" value="0.745"/> +<color name="brown" value="0.647 0.165 0.165"/> +<color name="navy" value="0 0 0.502"/> +<color name="pink" value="1 0.753 0.796"/> +<color name="seagreen" value="0.18 0.545 0.341"/> +<color name="turquoise" value="0.251 0.878 0.816"/> +<color name="violet" value="0.933 0.51 0.933"/> +<color name="darkblue" value="0 0 0.545"/> +<color name="darkcyan" value="0 0.545 0.545"/> +<color name="darkgray" value="0.663"/> +<color name="darkgreen" value="0 0.392 0"/> +<color name="darkmagenta" value="0.545 0 0.545"/> +<color name="darkorange" value="1 0.549 0"/> +<color name="darkred" value="0.545 0 0"/> +<color name="lightblue" value="0.678 0.847 0.902"/> +<color name="lightcyan" value="0.878 1 1"/> +<color name="lightgray" value="0.827"/> +<color name="lightgreen" value="0.565 0.933 0.565"/> +<color name="lightyellow" value="1 1 0.878"/> +<color name="title" value="0.4 0 0.4"/> +<dashstyle name="dashed" value="[4] 0"/> +<dashstyle name="dotted" value="[1 3] 0"/> +<dashstyle name="dash dotted" value="[4 2 1 2] 0"/> +<dashstyle name="dash dot dotted" value="[4 2 1 2 1 2] 0"/> +<textsize name="normal" value="\normalsize"/> +<textsize name="large" value="\large"/> +<textsize name="huge" value="\LARGE"/> +<textsize name="small" value="\normalsize"/> +<textstretch name="normal" value="2.8"/> +<textstretch name="large" value="2.8"/> +<textstretch name="huge" value="2.8"/> +<textstretch name="small" value="2.4"/> +<textstyle name="normal" begin="\begin{flushleft}" end="\end{flushleft}"/> +<textstyle name="center" begin="\begin{center}" end="\end{center}"/> +<textstyle name="itemize" begin="\begin{flushleft}\begin{itemize}" end="\end{itemize}\end{flushleft}"/> +<textstyle name="item" begin="\begin{flushleft}\begin{itemize}\item{}" end="\end{itemize}\end{flushleft}"/> +<gridsize name="16 pts (~6 mm)" value="16"/> +<gridsize name="32 pts (~12 mm)" value="32"/> +<gridsize name="10 pts (~3.5 mm)" value="10"/> +<gridsize name="20 pts (~7 mm)" value="20"/> +<gridsize name="14 pts (~5 mm)" value="14"/> +<gridsize name="28 pts (~10 mm)" value="28"/> +<gridsize name="56 pts (~20 mm)" value="56"/> +<anglesize name="90 deg" value="90"/> +<anglesize name="60 deg" value="60"/> +<anglesize name="45 deg" value="45"/> +<anglesize name="30 deg" value="30"/> +<anglesize name="22.5 deg" value="22.5"/> +<preamble> +\renewcommand\rmdefault{cmss} +\makeatletter +\leftmargini 1.5em +\leftmargin \leftmargini +\leftmarginii 1.2em +\leftmarginiii 1em +\def\@listI{\leftmargin\leftmargini + \parsep \z@ + \partopsep 3pt + \topsep \z@ + \itemsep \z@} +\@listI +\def\@listii {\leftmargin\leftmarginii + \labelwidth\leftmarginii + \advance\labelwidth-\labelsep + \topsep \z@ + \parsep \z@ + \itemsep \parsep} +\def\@listiii{\leftmargin\leftmarginiii + \labelwidth\leftmarginiii + \advance\labelwidth-\labelsep + \topsep \z@ + \parsep \z@ + \partopsep \z@ + \itemsep \topsep} +\makeatother +</preamble> +<layout paper="800 600" origin="32 0" frame="736 528" skip="32" crop="no"/> +<titlestyle pos="368 554" size="large" color="title" halign="center" valign="baseline"/> +<tiling name="falling" angle="-60" step="12" width="3"/> +<tiling name="rising" angle="30" step="12" width="3"/> +</ipestyle> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="221.536" height="19.3704" depth="0" halign="center" valign="baseline">Some Preliminaries</text> +<text transformations="translations" pos="16 512" stroke="black" type="minipage" width="704" height="116.909" depth="105.192" valign="top" size="small">\begin{itemize} +\item This description corresponds to the {\tt RU-RAU-split} branch for RAN infrastructure components (located in {\tt targets/DOCS/oai\_L1\_L2\_procedures.pdf}, editable with {\tt ipe}) +\item we describe +\begin{enumerate} +\item node functions +\item current functional splits and packet formats +\item RAN procedures +\item process scheduling +\end{enumerate} +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<image layer="alpha" matrix="0.910864 0 0 0.743119 40 12" rect="0 0 723 430" bitmap="3"/> +<text matrix="1 0 0 1 185 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="326.802" height="19.3704" depth="0" halign="center" valign="baseline">NGFI Harmonization in OAI</text> +<text transformations="translations" pos="0 528" stroke="black" type="minipage" width="736" height="100.324" depth="86.576" valign="top">\small +\begin{itemize} +\item New descriptions for OAI RAN infrastructure Node Functions +\begin{itemize} +\item{\tt NGFI\_RCC} : Radio Cloud Center +\item{\tt NGFI\_RAU} : Radio Aggregation Unit +\item{\tt NGFI\_RRU} : Remote Radio Unit +\item{\tt 3GPP\_BBU} : Baseband Unit +\item{\tt 3GPP\_eNodeB} : Complete eNodeB +\end{itemize} +\end{itemize} </text> +<text transformations="translations" pos="320 16" stroke="black" type="label" width="420.913" height="6.229" depth="1.99" valign="baseline" size="tiny">\small Source: China Mobile - {\tt http://www.windriver.com.cn/windforum/download/wf2015\_networking03.pdf}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<image layer="alpha" matrix="0.852308 0 0 0.885714 64 16" rect="0 0 325 558" bitmap="2"/> +<text matrix="0.809524 0 0 1.02381 36.1429 4.19048" transformations="translations" pos="384 496" stroke="black" type="minipage" width="384" height="139.135" depth="127.464" valign="top" size="small">\small\begin{itemize} +\item Current OAI implementation (RRU/RCC) supports either +\begin{itemize} +\item IF5 time-domain fronthaul ($>$ 1 GbE required) +\item IF4.5 split (FFTs) (280 Mbit/s/antenna port fronthaul – 20 MHz carrier) per carrier/sector +\item Soon IF2 (NFAPI) +\item IF1’ for “PDCP/RRC†soon (3GPP Fh-C/Fh-U) +\end{itemize} +\end{itemize}</text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="209.37" height="19.3928" depth="5.404" halign="center" valign="baseline">NGFI split points +</text> +<image matrix="0.866029 0 0 0.805556 358 8" rect="0 0 418 289" bitmap="1"/> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 188.731 -293.27" transformations="translations" pos="176 556" stroke="black" type="label" width="373.372" height="19.3704" depth="0" halign="center" valign="baseline">OAI RAN Software Architecture</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 90 -216" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 86 -212" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 82 -208" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 78 -204" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 10 -136" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 6 -132" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 2 -128" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -2 -124" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 86 -48" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 83 -44" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 80 -40" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 77 -36" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 10 45" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 6 49" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 2 53" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -2 57" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 64 18" transformations="translations" stroke="black" fill="1"> +528 64 m +528 32 l +640 32 l +640 64 l +h +</path> +<path matrix="1 0 0 1 56 26" transformations="translations" stroke="black" fill="1"> +528 64 m +528 32 l +640 32 l +640 64 l +h +</path> +<path transformations="translations" stroke="blue" dash="dashed" pen="heavier"> +528 101 m +528 48 l +736 48 l +736 101 l +h +</path> +<path matrix="1 0 0 1 0 -101" stroke="black" fill="white"> +392 376 m +392 296 l +512 296 l +512 376 l +h +</path> +<path matrix="1 0 0 1 -160 -135" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 -127" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 -127" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 -127" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 -127" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 -127" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1.25 0 0 1 -455.019 -129" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 0 74" stroke="black" fill="white"> +392 376 m +392 296 l +512 296 l +512 376 l +h +</path> +<path stroke="black"> +136 312 m +136 272 l +200 272 l +200 312 l +h +</path> +<path matrix="1.25 0 0 1 -456.019 50" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -161 42" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -168 48" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -6 61" stroke="black" fill="white"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -6 54" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -6 54" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 -6 50" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf LTE\\ +MODEM</text> +<path matrix="1 0 0 1 -176 58" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -176 58" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -176 58" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -176 58" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -176 58" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -304 58" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -304 58" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path stroke="black"> +96 408 m +96 360 l +208 360 l +208 408 l +h +</path> +<path matrix="1 0 0 1 -460 21" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -460 21" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 -472 15" transformations="translations" pos="576 384" stroke="black" type="minipage" width="96" height="20.5912" depth="6.608" valign="top" style="center">\tiny\bf LTE/NR/NB\\ +PDCP</text> +<path stroke="black" fill="1"> +128 320 m +128 280 l +192 280 l +192 320 l +h +</path> +<path matrix="1 0 0 1 -314 -86" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -314 -86" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 -449 -71" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf LTE\\ +RRC</text> +<path matrix="1 0 0 1 0 53" stroke="black"> +112 464 m +112 440 l +648 440 l +648 464 l +h +</path> +<path matrix="1 0 0 1 -122 42" stroke="black"> +432 224 m +432 224 l +432 224 l +432 224 l +h +</path> +<text matrix="1 0 0 1 -35 37" transformations="translations" pos="192 480" stroke="black" type="minipage" width="448" height="17.9352" depth="5.976" valign="top" size="small" style="center">\bf OSS/BSS/MEC</text> +<path stroke="green" arrow="normal/small"> +192 296 m +232 296 l +232 404 l +256 404 l +</path> +<path matrix="1 0 0 1 15 37" stroke="green" arrow="normal/small"> +144 288 m +144 320 l +</path> +<path matrix="1 0 0 1 -48 58" stroke="red" arrow="normal/small" rarrow="normal/small"> +384 368 m +448 368 l +</path> +<path matrix="1 0 0 1 -48 58" stroke="green" arrow="normal/small" rarrow="normal/small"> +384 352 m +448 352 l +</path> +<path matrix="1 0 0 1 0 37" stroke="blue" arrow="normal/small" rarrow="normal/small"> +152 456 m +152 368 l +</path> +<path matrix="1 0 0 1 0 37" stroke="blue" arrow="normal/small" rarrow="normal/small"> +304 456 m +304 408 l +</path> +<path matrix="1 0 0 1 0 37" stroke="blue" arrow="normal/small" rarrow="normal/small"> +456 456 m +456 416 l +</path> +<path matrix="1 0 0 1 0 37" stroke="blue" arrow="normal/small" rarrow="normal/small"> +600 456 m +600 409 l +</path> +<path matrix="1 0 0 1 -6 54" stroke="red" arrow="normal/small" rarrow="normal/small"> +512 368 m +576 368 l +</path> +<path matrix="1 0 0 1 -6 54" stroke="green" arrow="normal/small" rarrow="normal/small"> +512 352 m +576 352 l +</path> +<path stroke="red" arrow="normal/small" rarrow="normal/small"> +88 384 m +8 384 l +</path> +<path matrix="1 0 0 1 0 37" stroke="red" arrow="normal/small" rarrow="normal/small"> +128 264 m +8 264 l +</path> +<text matrix="1 0 0 1 140.731 -13.2696" transformations="translations" pos="176 556" stroke="black" type="label" width="250.205" height="19.3928" depth="5.404" halign="center" valign="baseline">OAI Functional Splits</text> +<path matrix="1 0 0 1 -176 58" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -176 42" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="11.816" depth="0" valign="top" style="center">\bf\tiny LTE-L1</text> +<path matrix="1 0 0 1 426 194" stroke="blue" arrow="normal/small" rarrow="normal/small"> +192 368 m +96 368 l +</path> +<path matrix="1 0 0 1 426 178" stroke="red" arrow="normal/small" rarrow="normal/small"> +192 368 m +96 368 l +</path> +<path matrix="1 0 0 1 426 162" stroke="green" arrow="normal/small" rarrow="normal/small"> +192 368 m +96 368 l +</path> +<text matrix="1 0 0 1 9 392" transformations="translations" pos="608 176" stroke="black" type="minipage" width="112" height="11.292" depth="0" valign="top" size="small">\bf\tiny Management</text> +<text matrix="1 0 0 1 11 375.418" transformations="translations" pos="608 176" stroke="black" type="minipage" width="144" height="11.9544" depth="0" valign="top" size="small">\bf\tiny data (user/control plane)</text> +<text matrix="1 0 0 1 9 360" transformations="translations" pos="608 176" stroke="black" type="minipage" width="112" height="11.292" depth="0" valign="top" size="small">\bf\tiny configuration</text> +<path matrix="1.25 0 0 1 -463 58" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 0.705114 -319 161.518" transformations="translations" pos="576 384" stroke="black" type="minipage" width="80" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf LTE\\ +MAC-RLC</text> +<path matrix="1 0 0 1 -76 21" stroke="black"> +288 432 m +288 432 l +288 432 l +288 432 l +h +</path> +<path stroke="blue" dash="dashed" pen="heavier"> +240 460 m +240 40 l +520 40 l +520 460 l +h +</path> +<path matrix="1 0 0 1 -48 21" stroke="black"> +384 416 m +384 416 l +384 416 l +384 416 l +h +</path> +<path matrix="1 0 0 1 0 37" stroke="blue" dash="dashed" pen="heavier"> +560 416 m +560 336 l +656 336 l +656 416 l +h +</path> +<path stroke="blue" dash="dashed" pen="heavier"> +88 456 m +88 40 l +216 40 l +216 221 l +216 261 l +216 456 l +100.8 456 l +88 456 l +</path> +<text matrix="1 0 0 1 -79 -148" transformations="translations" pos="160 176" stroke="blue" type="minipage" width="192" height="13.9468" depth="0" valign="top">\bf\tiny Radio-Cloud Center (RCC)</text> +<text matrix="1 0 0 1 -113 -258" transformations="translations" pos="480 288" stroke="blue" type="minipage" width="192" height="13.9468" depth="0" valign="top">\tiny\bf Radio-Access Unit (RAU)</text> +<path stroke="black"> +136 248 m +136 208 l +200 208 l +200 248 l +h +</path> +<path stroke="black" fill="1"> +128 256 m +128 216 l +192 216 l +192 256 l +h +</path> +<text matrix="1 0 0 1 -448 -134" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NR\\ +RRC</text> +<path stroke="green" arrow="normal/small"> +128 229 m +112 229 l +112 261 l +112 360 l +</path> +<path matrix="1 0 0 1 0 74" stroke="black" fill="white"> +488 368 m +488 304 l +504 304 l +504 368 l +h +</path> +<path matrix="1.25 0 0 1 -463.019 -121" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -304 -117" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -304 -117" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -48 -117" stroke="red" arrow="normal/small" rarrow="normal/small"> +384 368 m +448 368 l +</path> +<path matrix="1 0 0 1 -48 -117" stroke="green" arrow="normal/small" rarrow="normal/small"> +384 352 m +448 352 l +</path> +<path matrix="1 0 0 1 -176 -117" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -176 -136" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="11.816" depth="0" valign="top" style="center">\bf\tiny NR-L1</text> +<text matrix="1 0 0 0.705114 -318 -17.482" transformations="translations" pos="576 384" stroke="black" type="minipage" width="80" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NR\\ +MAC-RLC</text> +<path matrix="1 0 0 1 0 -101" stroke="black" fill="white"> +488 368 m +488 304 l +504 304 l +504 368 l +h +</path> +<text matrix="0 1 -1 0 724 -196" pos="576 224" stroke="black" type="label" width="58.2408" height="8.3016" depth="0" valign="baseline" size="small">\tiny PRECODE</text> +<text matrix="0 1 -1 0 724 -371" pos="576 224" stroke="black" type="label" width="58.2408" height="8.3016" depth="0" valign="baseline" size="small">\tiny PRECODE</text> +<path matrix="1 0 0 1 -6 -120" stroke="black" fill="white"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -6 -120" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -6 -120" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 -6 -131" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NR\\ +MODEM</text> +<path matrix="1 0 0 1 -6 -124" stroke="red" arrow="normal/small" rarrow="normal/small"> +512 368 m +576 368 l +</path> +<path matrix="1 0 0 1 -6 -123" stroke="green" arrow="normal/small" rarrow="normal/small"> +512 352 m +576 352 l +</path> +<path matrix="1 0 0 1 0 38" stroke="blue" dash="dashed" pen="heavier"> +560 231 m +560 160 l +656 160 l +656 231 l +h +</path> +<path matrix="1.25 0 0 1 -456.019 -44" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -22 -50" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -29 -44" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -304 -36" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -304 -36" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 0 53" stroke="red" arrow="normal/small" rarrow="normal/small"> +336 264 m +536 264 l +</path> +<path matrix="1 0 0 1 0 83" stroke="green" arrow="normal/small" rarrow="normal/small"> +336 248 m +536 248 l +</path> +<path matrix="1 0 0 1 -37 -34" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -37 -50" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="11.816" depth="0" valign="top" style="center">\bf\tiny LTE-L1</text> +<path matrix="1.25 0 0 1 -463 -36" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 0.705114 -319 67.518" transformations="translations" pos="576 384" stroke="black" type="minipage" width="80" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf LTE\\ +MAC-RLC</text> +<path matrix="1 0 0 1 139 -18" stroke="black" fill="white"> +488 368 m +488 304 l +504 304 l +504 368 l +h +</path> +<text matrix="0 1 -1 0 863 -288" pos="576 224" stroke="black" type="label" width="58.2408" height="8.3016" depth="0" valign="baseline" size="small">\tiny PRECODE</text> +<path matrix="1 0 0 1 74 -34" stroke="black" fill="white"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 74 -34" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 74 -34" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 74 -45" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf LTE\\ +MODEM</text> +<path matrix="1 0 0 1 0 68" transformations="translations" stroke="green" fill="white" arrow="normal/small"> +232 264 m +256 264 l +</path> +<path transformations="translations" stroke="red" arrow="normal/small" rarrow="normal/small"> +256 424 m +224 424 l +224 316 l +256 316 l +</path> +<path matrix="1 0 0 1 0 37" transformations="translations" stroke="red" cap="1"> +64 264 m +64 264 l +</path> +<path matrix="1 0 0 1 0 70" stroke="blue" dash="dashed" pen="heavier"> +528 288 m +528 208 l +736 208 l +736 288 l +h +</path> +<path matrix="1.25 0 0 1 -456.019 -204" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1.25 0 0 1 -463 -196" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 0.705114 -319 -92.482" transformations="translations" pos="576 384" stroke="black" type="minipage" width="80" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NR\\ +MAC-RLC</text> +<path matrix="1.25 0 0 1 -463 -283" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 0.705114 -319 -179.482" transformations="translations" pos="576 384" stroke="black" type="minipage" width="80" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NB-IoT\\ +MAC-RLC</text> +<path matrix="1 0 0 1 0 -22" stroke="red" arrow="normal/small" rarrow="normal/small"> +128 264 m +8 264 l +</path> +<path matrix="1 0 0 1 -22 -217" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -29 -211" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<path matrix="1 0 0 1 0 -115" stroke="red" arrow="normal/small" rarrow="normal/small"> +336 264 m +536 264 l +</path> +<path matrix="1 0 0 1 0 -83" stroke="green" arrow="normal/small" rarrow="normal/small"> +336 248 m +536 248 l +</path> +<path matrix="1 0 0 1 -37 -201" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -37 -217" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="11.816" depth="0" valign="top" style="center">\bf\tiny NR-L1</text> +<path matrix="1 0 0 1 139 -185" stroke="black" fill="white"> +488 368 m +488 304 l +504 304 l +504 368 l +h +</path> +<text matrix="0 1 -1 0 863 -455" pos="576 224" stroke="black" type="label" width="58.2408" height="8.3016" depth="0" valign="baseline" size="small">\tiny PRECODE</text> +<path matrix="1 0 0 1 74 -201" stroke="black" fill="white"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<path matrix="1 0 0 1 74 -201" stroke="black"> +624 336 m +624 336 l +624 336 l +624 336 l +h +</path> +<path matrix="1 0 0 1 74 -201" stroke="black"> +608 336 m +608 336 l +608 336 l +608 336 l +h +</path> +<text matrix="1 0 0 1 74 -212" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NR\\ +MODEM</text> +<path matrix="1 0 0 1 0 -97" stroke="blue" dash="dashed" pen="heavier"> +528 288 m +528 208 l +736 208 l +736 288 l +h +</path> +<text matrix="1 0 0 1 71 -258" transformations="translations" pos="480 288" stroke="blue" type="minipage" width="192" height="13.9468" depth="0" valign="top">\tiny\bf Remote Radio-Unit (RRU)</text> +<path stroke="red" arrow="normal/small" rarrow="normal/small"> +336 72 m +576 72 l +</path> +<path stroke="green" arrow="normal/small" rarrow="normal/small"> +336 86 m +576 88 l +</path> +<path matrix="1 0 0 1 -452 -282" stroke="black" fill="1"> +576 384 m +576 336 l +640 336 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -452 -293" transformations="translations" pos="576 384" stroke="black" type="minipage" width="64" height="20.1796" depth="6.244" valign="top" style="center">\tiny\bf NB-IoT\\ +RRC</text> +<path matrix="1 0 0 1 -8 -193" stroke="red" arrow="normal/small" rarrow="normal/small"> +128 264 m +8 264 l +</path> +<path transformations="translations" stroke="green" rarrow="normal/small"> +104 360 m +104 88 l +120 88 l +</path> +<path transformations="translations" stroke="green" arrow="normal/small"> +192 88 m +256 88 l +</path> +<path matrix="1 0 0 1 48 34" transformations="translations" stroke="black" fill="white"> +528 64 m +528 32 l +640 32 l +640 64 l +h +</path> +<text matrix="1 0 0 1 2 -288" transformations="translations" pos="576 384" stroke="black" type="minipage" width="104" height="21.9296" depth="7.98" valign="top" style="center">\tiny\bf NB-IoT\\ +L1/MODEM</text> +<path transformations="translations" stroke="red" fill="white" arrow="normal/small"> +224 384 m +208 384 l +</path> +<path transformations="translations" stroke="green" fill="white" arrow="normal/small"> +192 240 m +256 240 l +</path> +<path transformations="translations" stroke="green" arrow="normal/small"> +232 240 m +232 168 l +256 168 l +</path> +<path transformations="translations" stroke="green" cap="1"> +224 192 m +224 192 l +</path> +<path transformations="translations" stroke="green" cap="1"> +224 192 m +224 192 l +</path> +<path transformations="translations" stroke="green" arrow="normal/small"> +224 312 m +224 72 l +256 72 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 188.731 2.73037" transformations="translations" pos="176 556" stroke="black" type="label" width="250.205" height="19.3928" depth="5.404" halign="center" valign="baseline">OAI Functional Splits</text> +<text transformations="translations" pos="14.7471 512.821" stroke="black" type="minipage" width="707.342" height="140.266" depth="128.592" valign="top" size="small">\tiny\begin{itemize} +\item OAI currently implements the following entities in openairinterface5g +\begin{itemize} +\item LTE-MODEM (eNB 36.211 OFDM modulation/demodulation) +\item LTE-L1 (eNB 36.211/212/213) +\item LTE-MACRLC (eNB 36.321/322) +\item LTE-PDCP (eNB PDCP/GTPU 36.323) +\item LTE-RRC (eNB RRC/SCTP 36.331) +\end{itemize} +\item Each entity comprises +\begin{itemize} +\item a northbound interface (backhaul/midhaul/fronthaul and configuration) +\item a southbound interface (midaul/fronthaul and configuration) +\item one or two management interfaces +\item Three computing nodes +\begin{itemize} +\item {\bf Radio Cloud Center (RCC)} : multiple RRC/PDCP entities +\item {\bf Radio-Access Unit (RAU)}: multiple MACRLC entities with medium-latency midhaul and L1 entities with low-latency fronthaul. +\item {\bf Remote Radio-Unit (RRU)}: Equipment at radio site. Varying degrees of processing elements depending on fronthaul/midhaul interface. +\end{itemize} +\end{itemize} +\item Each entity has a configuration which is a local file or received via the management interface +\item default interface between all entities is implemented using a UDP socket. Transport is configurable via a dynamically-loadable networking device +\end{itemize}</text> +<path stroke="black"> +288 192 m +288 64 l +432 64 l +432 192 l +h +</path> +<text transformations="translations" pos="288 144" stroke="black" type="minipage" width="144" height="19.3928" depth="5.404" valign="top" style="center">OAI entity</text> +<path matrix="1 0 0 1 0 23" stroke="red" arrow="normal/small" rarrow="normal/small"> +336 171 m +336 208 l +</path> +<path matrix="1 0 0 1 0 23" stroke="green" arrow="normal/small" rarrow="normal/small"> +384 171 m +384 208 l +</path> +<path matrix="1 0 0 1 0 -144" stroke="red" arrow="normal/small" rarrow="normal/small"> +336 171 m +336 208 l +</path> +<path matrix="1 0 0 1 0 -144" stroke="green" arrow="normal/small" rarrow="normal/small"> +384 171 m +384 208 l +</path> +<path matrix="1 0 0 1 0 47" stroke="blue" arrow="normal/small" rarrow="normal/small"> +240 80 m +288 80 l +</path> +<path matrix="1 0 0 1 0 71" stroke="blue" arrow="normal/small" rarrow="normal/small"> +240 80 m +288 80 l +</path> +<path matrix="5.5 0 0 0.5 -1224 100" stroke="blue"> +16 0 0 16 288 224 e +</path> +<path matrix="5.5 0 0 0.5 -1224 -60" stroke="blue"> +16 0 0 16 288 224 e +</path> +<text transformations="translations" pos="464 224" stroke="blue" type="minipage" width="144" height="10.128" depth="0" valign="top" size="small">\tiny\bf Northbound interface</text> +<text matrix="1 0 0 1 0 -160" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="144" height="10.128" depth="0" valign="top" size="small">\tiny\bf Southbound interface</text> +<text matrix="1 0 0 1 -144 -199" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="32" height="10.128" depth="0" valign="top" size="small">\tiny\bf data</text> +<text matrix="1 0 0 1 -144 16" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="32" height="10.128" depth="0" valign="top" size="small">\tiny\bf data</text> +<text matrix="1 0 0 1 -96 -199" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="112" height="18.468" depth="6.504" valign="top" size="small">\tiny\bf in-band configuration</text> +<text matrix="1 0 0 1 -96 34" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="112" height="18.468" depth="6.504" valign="top" size="small">\tiny\bf in-band configuration</text> +<text matrix="1 0 0 1 -288 -55" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="64" height="11.9544" depth="0" valign="top" size="small">\tiny\bf OSS/BSS</text> +<text matrix="1 0 0 1 -288 -79" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="64" height="10.128" depth="0" valign="top" size="small">\tiny\bf FlexRAN</text> +<path matrix="1 0 0 1 0 -1" stroke="blue" arrow="normal/small" rarrow="normal/small"> +240 80 m +288 80 l +</path> +<text matrix="1 0 0 1 -248 -127" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="64" height="9.6312" depth="0" valign="top" size="small">\tiny\tt .conf</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="0.92926 0 0 1.00204 -473.9 3.55763" stroke="black" fill="lightgray"> +511.895 513.539 m +511.895 14.2386 l +734.284 14.2386 l +734.284 513.539 l +h +</path> +<path matrix="0.880259 0 0 1.00521 -236.182 1.22986" stroke="black" fill="lightgray"> +511.895 513.539 m +511.895 14.2386 l +734.284 14.2386 l +734.284 513.539 l +h +</path> +<path matrix="1 0 0 1.00204 -98.2818 2.84025" stroke="black" fill="lightgray"> +511.895 513.539 m +511.895 14.2386 l +734.284 14.2386 l +734.284 513.539 l +h +</path> +<path matrix="1 0 0 1.1 208 -43.2" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="1 0 0 1.1 0 -43.2" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<text matrix="1 0 0 1 185 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="313.978" height="20.9244" depth="6.972" halign="center" valign="baseline">Functional Splits (Current)</text> +<path matrix="0.791667 0 0 1 -126.042 -156.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 139 -128.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -126.25 -109" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -126.25 -64" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 133.792 -35.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 138.792 -80.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -174.042 -156.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 91 -128.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -174.25 -109" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -174.25 -64" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 85.792 -35.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 90.792 -80.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -222.25 -64" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 37.792 -35.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RRC +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -222.25 -16" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 37.792 7.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-C +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -469.028 -12.3492" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 108.792 6.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-U +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -126.042 -204.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 139 -176.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -174.042 -204.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 91 -176.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX +\end{tiny} +</text> +<path matrix="1 0 0 1 -255 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1 0 0 1 -326 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1.68745 0 0 0.646102 -469.028 -103.883" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 101.792 -228.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt rf\_device} +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 81.958 -157.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 347 -129.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 81.75 -110" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 81.75 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 341.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 346.792 -81.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 33.958 -157.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 299 -129.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 33.75 -110" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 33.75 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 293.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 298.792 -81.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -14.25 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 245.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RRC +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -14.25 -17" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 245.792 6.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-C +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -261.028 -13.3492" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 316.792 5.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-U +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 81.958 -205.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 347 -177.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 33.958 -205.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 299 -177.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -261.028 -101.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 309.792 -229.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 -70 -65" transformations="translations" pos="176 556" stroke="black" type="label" width="170.52" height="19.3704" depth="0" halign="center" valign="baseline">3GPP\_eNodeB</text> +<text matrix="1 0 0 1 138 -65" transformations="translations" pos="176 556" stroke="black" type="label" width="134.604" height="19.3704" depth="0" halign="center" valign="baseline">3GPP\_BBU</text> +<text matrix="1 0 0 1 -13 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="48" height="10.128" depth="0" valign="top" size="small">\tiny to MME</text> +<text matrix="1 0 0 1 51 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to S-PGw</text> +<path matrix="1 0 0 1 -47 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1 0 0 1 -118 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="1 0 0 1 195 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="48" height="10.128" depth="0" valign="top" size="small">\tiny to MME</text> +<text matrix="1 0 0 1 259 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to S-PGw</text> +<path stroke="black" fill="lightblue"> +160 112 m +160 112 l +160 112 l +160 112 l +h +</path> +<path stroke="black" fill="lightblue"> +144 112 m +144 112 l +144 112 l +144 112 l +h +</path> +<path matrix="1.68745 0 0 0.991372 -469.028 -289.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 101.792 -264.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="16.8048" depth="4.848" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt USB3 or PCIe} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -261.028 -289.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 300.792 -264.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF5 / ethernet} +\end{tiny} +</text> +<path matrix="1 0 0 1.1 416 -43.2" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="0.791667 0 0 1 289.958 -157.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 555 -129.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 289.75 -110" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 289.75 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 549.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 554.792 -81.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 241.958 -157.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 507 -129.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 241.75 -110" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 241.75 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 501.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 506.792 -81.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 193.75 -65" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 453.792 -36.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RRC +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 193.75 -17" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 453.792 6.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-C +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -53.028 -13.3492" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 524.792 5.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-U +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 289.958 -205.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 241.958 -205.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 507 -163.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY RX +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -53.028 -101.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 517.792 -229.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 346 -65" transformations="translations" pos="176 556" stroke="black" type="label" width="215.964" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RCC (IF4.5)</text> +<path matrix="1 0 0 1 161 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1 0 0 1 90 31" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="1 0 0 1 403 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="48" height="10.128" depth="0" valign="top" size="small">\tiny to MME</text> +<text matrix="1 0 0 1 467 0" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to S-PGw</text> +<path matrix="1.68745 0 0 0.991372 -53.028 -289.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 508.792 -264.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF4p5 / ethernet} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 555 -163.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY TX +\end{tiny} +</text> +<path matrix="1 0 0 1 163 -334" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 406.604 -432" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RRU</text> +<path matrix="1 0 0 1 -45 -334" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 198.604 -432" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="18.468" depth="6.504" valign="top" size="small">\tiny to NGFI\_RRU or RRH\_gw</text> +<path matrix="1 0 0 1 -253.457 -333.956" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 -11.8528 -430.956" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to RF Device</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1.01725 0 0 0.848434 249.573 104.961" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="1.00369 0 0 1.08732 29.991 -6.98372" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="1 0 0 0.900567 29 11.9552" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="0.791667 0 0 1 -97.042 -189.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 168 -161.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -97.25 -142" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -97.25 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 162.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 167.792 -113.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -145.042 -189.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 120 -161.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -145.25 -142" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -145.25 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 114.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 119.792 -113.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -193.25 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 66.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RRC +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 -193.25 -49" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 66.792 -25.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-C +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -440.028 -45.3492" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 137.792 -26.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-U +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -440.028 -78.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 130.792 -206.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 -41 -97" transformations="translations" pos="176 556" stroke="black" type="label" width="208.216" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RCC (IF1'')</text> +<path matrix="1 0 0 1 -226 -1" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1 0 0 1 -297 -1" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="1 0 0 1 16 -32" transformations="translations" pos="48 480" stroke="black" type="minipage" width="48" height="10.128" depth="0" valign="top" size="small">\tiny to MME</text> +<text matrix="1 0 0 1 80 -32" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to S-PGw</text> +<path matrix="1.68745 0 0 0.991372 -440.028 -266.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 113.792 -241.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="90" height="17.6496" depth="5.664" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF1pp} / ethernet +\end{tiny} +</text> +<path matrix="1 0 0 0.651275 253 119.649" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="0.791667 0 0 1 126.75 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 386.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 78.75 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 338.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 30.75 -97" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 290.792 -68.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RRC +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 30.75 -49" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 290.792 -25.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-C +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -216.028 -45.3492" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 361.792 -26.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +GTP-U +\end{tiny} +</text> +<path matrix="2.69329 0 0 0.638421 -595.954 13.42" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 334.792 -114.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 183 -97" transformations="translations" pos="176 556" stroke="black" type="label" width="202.017" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RCC (IF1')</text> +<path matrix="1 0 0 1 -2 -1" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1 0 0 1 -73 -1" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="1 0 0 1 240 -32" transformations="translations" pos="48 480" stroke="black" type="minipage" width="48" height="10.128" depth="0" valign="top" size="small">\tiny to MME</text> +<text matrix="1 0 0 1 304 -32" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to S-PGw</text> +<path matrix="1.68745 0 0 0.991372 -216.028 -174.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 337.792 -149.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="90" height="17.6496" depth="5.664" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF1p} / ethernet +\end{tiny} +</text> +<text matrix="2.11243 0 0 1 36.6036 -461" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RRU</text> +<path matrix="1 0 0 1 -226 -313" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 15.604 -408" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RAU</text> +<path matrix="1 0 0 1 -1 -222" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 240.604 -317" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RAU</text> +<text matrix="1 0 0 1 185 -0.999538" transformations="translations" pos="176 556" stroke="black" type="label" width="313.978" height="20.9244" depth="6.972" halign="center" valign="baseline">Functional Splits (Current)</text> +<path matrix="1.00369 0 0 1.08732 500.993 -5.7664" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="0.727273 0 0 0.742424 530.364 32.2727" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="0.791667 0 0 1 351.958 -178.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 303.958 -178.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 569 -136.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY RX +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 8.972 -74.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 579.792 -202.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 433 -92" transformations="translations" pos="176 556" stroke="black" type="label" width="200.276" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RAU(IF1'')</text> +<path matrix="1.68745 0 0 0.991372 8.972 -262.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 570.792 -237.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF4p5 / ethernet} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 617 -136.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY TX +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 7.934 21.42" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 581.792 -106.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 8.972 -82.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.769443 0 0 0.141445 570.792 268.279" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF1pp / ethernet} +\end{tiny} +</text> +<path matrix="1 0 0 1 223 -40" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 464.604 -71" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RCC</text> +<path matrix="1 0 0 1 223 -312" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 464.604 -407" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to NGFI\_RRU</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1.0663 0 0 1.11251 444.141 -16.4274" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="1.06788 0 0 1.10769 212.939 -13.7478" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="1 0 0 1 0 37" stroke="black" fill="lightgray"> +1.83417 462.604 m +1.83417 50.8252 l +207.006 50.8252 l +207.006 462.604 l +h +</path> +<path matrix="0.727273 0 0 0.546841 27.364 94.7646" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -494.028 5.42" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 76.792 -122.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 -72 -92" transformations="translations" pos="176 556" stroke="black" type="label" width="195.818" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RRU (IF5)</text> +<path matrix="1.68745 0 0 0.991372 -494.028 -100.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 67.792 -75.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF5/ ethernet} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -494.028 -27.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 76.792 -155.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt rf\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 147 -92" transformations="translations" pos="176 556" stroke="black" type="label" width="217.515" height="20.9244" depth="6.972" halign="center" valign="baseline">NGFI\_RRU (IF4.5)</text> +<path matrix="1 0 0 1 -279.958 -59.1734" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 -59.355 -78.1734" transformations="translations" pos="48 480" stroke="black" type="minipage" width="128" height="18.0648" depth="6.12" valign="top" size="small" style="center">\tiny to NGFI\_RCC, NGFI\_RAU,3GPP\_BBU</text> +<path matrix="1 0 0 1 -280 -274" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 -38.396 -369" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to RF Device</text> +<path matrix="1.67303 0 0 1.24455 -489.268 -322.215" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 76.792 -188.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="23.9736" depth="12.024" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt USB3, PCIe, CPRI} +\end{tiny} +</text> +<path matrix="0.7308 0 0 0.711699 250.308 23.5462" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -271.028 5.42" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 299.792 -122.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.991372 -271.028 -100.349" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 290.792 -75.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF4p5/ ethernet} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -271.028 -77.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 299.792 -205.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt rf\_device} +\end{tiny} +</text> +<path matrix="1 0 0 1 -56.958 -59.1734" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 163.645 -78.1734" transformations="translations" pos="48 480" stroke="black" type="minipage" width="128" height="17.2968" depth="5.352" valign="top" size="small" style="center">\tiny to NGFI\_RCC, NGFI\_RAU</text> +<path matrix="1 0 0 1 -57 -320" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 184.604 -424" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to RF Device</text> +<path matrix="1.67303 0 0 1.24455 -266.268 -372.215" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 299.792 -238.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="23.9736" depth="12.024" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt USB3, PCIe, CPRI} +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 71.958 -189.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 23.958 -189.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 289 -154.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +lower-PHY RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 337 -154.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +lower-PHY TX +\end{tiny} +</text> +<path matrix="0.754883 0 0 0.844765 480.935 6.70954" stroke="black" fill="lightyellow"> +16 432 m +16 112 l +192 112 l +192 432 l +h +</path> +<path matrix="0.791667 0 0 1 303.97 -144.528" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.74239 0 0 0.607628 -58.1448 -70.7751" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 530.804 -210.953" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 569.012 -102.277" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY TX +\end{tiny} +</text> +<path matrix="1.7325 0 0 0.638421 -53.9193 44.2159" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 534.804 -83.9531" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.79658 0 0 0.968027 -76.0285 -53.4485" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.769443 0 0 0.141445 521.804 288.075" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="20.832" depth="8.856" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF1pp\_4P5 / ethernet} +\end{tiny} +</text> +<path matrix="1 0 0 1 174.012 -21.2041" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<text matrix="2.11243 0 0 1 385.616 -56.2041" transformations="translations" pos="48 480" stroke="black" type="minipage" width="143.13" height="10.896" depth="0" valign="top" size="small">\tiny to NGFI\_RCC, NGFI\_RAU</text> +<path matrix="0.924035 0 0 1 204.183 -321.204" stroke="black" fill="lightblue" arrow="normal/normal" rarrow="normal/normal"> +384 432 m +384 384 l +</path> +<path matrix="1.67303 0 0 1.24455 -34.3906 -373.77" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 531.669 -240.304" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="23.9736" depth="12.024" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt USB3, PCIe, CPRI} +\end{tiny} +</text> +<text matrix="2.11243 0 0 1 420.344 -422.726" transformations="translations" pos="48 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny to RF Device</text> +<text matrix="1 0 0 1 185 -0.999076" transformations="translations" pos="176 556" stroke="black" type="label" width="313.978" height="20.9244" depth="6.972" halign="center" valign="baseline">Functional Splits (Current)</text> +<text matrix="1 0 0 1 0 33" transformations="translations" pos="453.069 456.148" stroke="black" type="minipage" width="204.455" height="36.8592" depth="22.96" valign="top" style="center">NGFI\_RRU\par +(IF1'')</text> +<path matrix="0.791667 0 0 1 303.674 -194.932" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 255.674 -194.932" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 520.716 -159.681" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +lower-PHY RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 568.716 -159.681" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +lower-PHY TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 255.97 -144.528" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 521.012 -102.277" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="27.4872" depth="15.552" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY RX +\end{tiny} +</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 188.731 2.73037" transformations="translations" pos="176 556" stroke="black" type="label" width="352.257" height="19.3928" depth="5.404" halign="center" valign="baseline">Some Notes on usage of splits</text> +<text transformations="translations" pos="14.7471 512.821" stroke="black" type="minipage" width="707.342" height="239.641" depth="226.212" valign="top">\tiny\begin{itemize} +\item IF4p5 corresponds to the split-point at the input (TX) and output (RX) of the OFDM symbol generator (i.e. frequency-domain signals). According to NGFI, IF4 is "Resource mapping and IFFT" and "FFT and Resource demapping". We currently do not try to exploit multiplexing gains for unused spectral components. So, IF4p5 is simply compressed transmitted or received resource elements in the usable channel band. +\item The simplest deployment for DAS (indoor) is one NGFI\_RCC (IF4p5) and many NGFI\_RRU (IF4p5). Spatio-temportal filtering (Precoding, later) is done in RCC and RRU perform IFFT/FFT and signal generation/acquisition. Fronthaul rates in this case are feasible with 1GbE copper links. This allows for PoE in addition to fronthaul data. +\item More complex indoor, for instance with RCC in a common data center with outdoor RRS, could be +\begin{enumerate} + \item RCC-RAU with IF1'', RAU-RRU with IF4p5. Spatio-temporal filtering is done in frequency-domain in RAU along with full TX and RX processing (L1/L2) for the indoor RRS. Note that IF1' fronthaul on TX to RRU would be difficult because spatio-temporal filtering should be used. RRU does only IFFT/FFT and signal generation/acquisition +\item RCC-RAU with IF1', RAU-RRU with IF4p5. Here RCC does L2, RAU does L1 and precoding for RRS. +\end{enumerate} +\item A massive-MIMO solution would consist either of +\begin{enumerate} +\item an embedded RAU with processing (Spatio-temporal in frequency-domain, lower/upper PHY TX/RX) like the IF1' DAS solution above +\item or more simply a high-speed fronthaul (IF4p5) with an RAU for multiple sites +\item directly connected to RCC via high-speed IF4p5 (several virtual cells, precoder and IFFT/FFT in array). +\end{enumerate} +\item RCC solution with IF1'' would cater to evolved-PDCP for heterogenity (4G,5G,WIFI,IoT) +\item Currently supported node functionalities +\begin{enumerate} +\item {\tt 3GPP\_eNodeB} +\item {\tt 3GPP\_eNodeB\_BBU} [NGFI\_IF5] +\item {\tt NGFI\_RCC} [NGFI\_IF4p5] +\item {\tt NGFI\_RRU} [NGFI\_IF5] +\item {\tt NGFI\_RRU} [NGFI\_IF4p5] +\end{enumerate} +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 188.731 2.73037" transformations="translations" pos="176 556" stroke="black" type="label" width="233.391" height="19.3928" depth="5.404" halign="center" valign="baseline">RU - L1 negotiation</text> +<path matrix="1 0 0 1 -16 64" stroke="black" fill="lightblue"> +64 448 m +64 256 l +256 256 l +256 448 l +h +</path> +<path matrix="1 0 0 1 368 64" stroke="black" fill="lightblue"> +64 448 m +64 256 l +256 256 l +256 448 l +h +</path> +<text matrix="1 0 0 1 -16 16" transformations="translations" pos="64 416" stroke="black" type="minipage" width="192" height="19.3928" depth="5.404" valign="top" style="center">RRU Entity</text> +<text matrix="1 0 0 1 368 32" transformations="translations" pos="64 416" stroke="black" type="minipage" width="192" height="36.8592" depth="22.96" valign="top" style="center">RAU/RCC Entity</text> +<path matrix="1 0 0 1 -16 64" stroke="black" fill="lightblue" arrow="normal/normal"> +544 192 m +544 256 l +</path> +<path matrix="1 0 0 1 -16 64" stroke="red" fill="lightblue" arrow="normal/normal"> +256 320 m +448 320 l +</path> +<path matrix="1 0 0 1 -16 64" stroke="red" fill="lightblue" arrow="normal/normal"> +448 288 m +256 288 l +</path> +<path matrix="1 0 0 1 -400 64" stroke="black" fill="lightblue" arrow="normal/normal"> +544 192 m +544 256 l +</path> +<text matrix="1 0 0 1 -312 33" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="64" height="11.2364" depth="0" valign="top">\tiny\tt .conf</text> +<text matrix="1 0 0 1 72 33" transformations="translations" pos="464 224" stroke="blue" type="minipage" width="64" height="11.2364" depth="0" valign="top">\tiny\tt .conf</text> +<text matrix="1 0 0 1 -199 158" transformations="translations" pos="464 224" stroke="black" type="minipage" width="160" height="21.1652" depth="7.196" valign="top">\tiny\tt fronthaul data (IF5,IF4p5)</text> +<path matrix="1 0 0 1 -16 160" stroke="green" fill="lightblue" arrow="normal/normal"> +256 320 m +448 320 l +</path> +<path matrix="1 0 0 1 -16 160" stroke="green" fill="lightblue" arrow="normal/normal"> +448 288 m +256 288 l +</path> +<text matrix="1 0 0 1 -215 235" transformations="translations" pos="464 224" stroke="black" type="minipage" width="176" height="13.3672" depth="0" valign="top">\tiny\tt RRU control/config</text> +<text matrix="1 0 0 1 0 80" transformations="translations" pos="32 160" stroke="black" type="minipage" width="672" height="116.743" depth="105.024" valign="top" size="small">\begin{small} +Control and Configuration protocol +\begin{enumerate} +\item RAU$\rightarrow$ RRU : heartbeat (capabilities request) +\item RRU$\rightarrow$ RAU: capabilities indication +\item RAU$\rightarrow$ RRU: configuration (band, dl\_Carrier,ul\_Carrier, dl\_RS\_EPRE, rx/tx attenuation) +\end{enumerate} +\end{small} +During steady state, the control port manages the link quality and status (packet losses, synchronization state, start/stop, etc.)</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" transformations="translations" pos="16 512" stroke="black" type="minipage" width="704" height="186.004" depth="172.452" valign="top">\begin{small} +\begin{itemize} +\item IF5 interface +\begin{itemize} +\item DL subframes with timestamp (16-bit samples) +\item UL subframes with timestamp (16-bit samples) +\item optional A-law compression (13$\rightarrow$8bit) +\end{itemize} +\item IF4p5 interface +\begin{itemize} +\item DL packets, ofdm symbols with frame/subframe/symbol count +\item UL packets, ofdm symbols with frame/subframe/symbol count (16-bit) +\item UL PRACH packets with frame/subframe count (16-bit) +\item optional A-law compression (13$\rightarrow$8bit) +\end{itemize} +\end{itemize} +\end{small}</text> +<text matrix="1 0 0 1 188.731 2.73037" transformations="translations" pos="176 556" stroke="black" type="label" width="225.333" height="19.3928" depth="5.404" halign="center" valign="baseline">RU - L1 data plane</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="3.99386 0 0 1 -2166.33 147.732" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<text matrix="1 0 0 1 185 -0.999076" transformations="translations" pos="176 556" stroke="black" type="label" width="317.156" height="20.9244" depth="6.972" halign="center" valign="baseline">IF5 Packet Format (16-bit)</text> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 102.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 262.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 422.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<text matrix="1 0 0 1 -53.6718 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">0</text> +<text matrix="1 0 0 1 106.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">16</text> +<text matrix="1 0 0 1 266.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">32</text> +<text matrix="1 0 0 1 426.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">48</text> +<text matrix="1 0 0 1 73.3282 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">15</text> +<text matrix="1 0 0 1 233.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">31</text> +<text matrix="1 0 0 1 393.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">47</text> +<text matrix="1 0 0 1 553.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">63</text> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="violet"> +64 320 m +64 288 l +544 288 l +544 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +544 320 m +544 288 l +704 288 l +704 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +64 288 m +64 256 l +384 256 l +384 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightyellow"> +384 288 m +384 256 l +544 256 l +544 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightgreen"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<text matrix="1 0 0 1 45.3282 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="184.702" height="14.9448" depth="0" valign="baseline" size="small">\small Destination Address</text> +<text matrix="1 0 0 1 435.328 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="61.9848" height="14.9448" depth="0" valign="baseline" size="small">\small Source</text> +<text matrix="1 0 0 1 237.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="135.391" height="16.1424" depth="5.376" valign="baseline" size="small">\small Type (0x1234)</text> +<text matrix="1 0 0 1 421.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="93.8976" height="14.952" depth="4.176" valign="baseline" size="small">\small RF Config</text> +<text matrix="1 0 0 1 30.3282 218.732" transformations="translations" pos="96 224" stroke="black" type="label" width="71.9664" height="14.9448" depth="0" valign="baseline" size="small">\small Address</text> +<path matrix="1 0 0 1 -57.6718 162.732" stroke="black" fill="red"> +64 160 m +64 128 l +384 128 l +384 160 l +h +</path> +<text matrix="1 0 0 1 -52.6718 75.7323" transformations="translations" pos="96 224" stroke="black" type="label" width="214.279" height="14.952" depth="4.176" valign="baseline" size="small">\small Frame Check Sequence</text> +<path matrix="1 0 0 1 0.328186 99.7323" stroke="black"> +256 240 m +256 240 l +256 240 l +</path> +<text matrix="1 0 0 1 176.328 189.732" transformations="translations" pos="96 224" stroke="black" type="label" width="103.87" height="14.952" depth="4.176" valign="baseline" size="small">\small Timestamp</text> +<path matrix="1 0 0 1 1.3282 309" stroke="black" fill="lightblue" tiling="falling"> +5 63.5079 m +5 46.9999 l +645 46.9999 l +645 63.5079 l +h +</path> +<path matrix="1 0 0 1 -57.6718 148" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 148" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 100" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -57.6718 100" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +256 240 m +256 240 l +256 240 l +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<path matrix="1 0 0 1 -320.398 99.9995" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<text matrix="1 0 0 1 17 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_0$</text> +<text matrix="1 0 0 1 166 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_0$</text> +<text matrix="1 0 0 1 335 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_1$</text> +<text matrix="1 0 0 1 492 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_1$</text> +<text matrix="1 0 0 1 -3 89" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="13.0848" depth="1.128" valign="top" size="small">\tiny $Q_{N-2}$</text> +<text matrix="1 0 0 1 150 89" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="13.0848" depth="1.128" valign="top" size="small">\tiny $Q_{N-2}$</text> +<text matrix="1 0 0 1 320 89" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="13.0848" depth="1.128" valign="top" size="small">\tiny $I_{N-1}$</text> +<text matrix="1 0 0 1 477 89" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="13.0848" depth="1.128" valign="top" size="small">\tiny $Q_{N-1}$</text> +<text matrix="1 0 0 1 0 43" transformations="translations" pos="0 240" stroke="black" type="minipage" width="736" height="43.8816" depth="31.968" valign="top" size="small">\tiny +\begin{itemize} +\item {\bf Type:} 2 byte (16 bit) field that specifies the RoE protocol +\item {\bf RX Config:} 16-bit. Currently just antenna index (0-7). Can later be used for gain/timing adjustments. +\item {\bf Timstamp:} Timestamp in samples of the first sample of the received packet. +\end{itemize} +\begin{itemize} +\item {\bf data block :} Uncompressed IQ samples, 16-bit resolution for each real and imaginary component. $N$ complex samples per packet. $N$ can be configured at initialization. +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 185 -0.999076" transformations="translations" pos="176 556" stroke="black" type="label" width="303.209" height="20.9244" depth="6.972" halign="center" valign="baseline">IF5 Packet Format (8-bit)</text> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 102.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 262.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 422.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<text matrix="1 0 0 1 -53.6718 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">0</text> +<text matrix="1 0 0 1 106.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">16</text> +<text matrix="1 0 0 1 266.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">32</text> +<text matrix="1 0 0 1 426.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">48</text> +<text matrix="1 0 0 1 73.3282 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">15</text> +<text matrix="1 0 0 1 233.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">31</text> +<text matrix="1 0 0 1 393.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">47</text> +<text matrix="1 0 0 1 553.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">63</text> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="violet"> +64 320 m +64 288 l +544 288 l +544 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +544 320 m +544 288 l +704 288 l +704 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +64 288 m +64 256 l +384 256 l +384 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightyellow"> +384 288 m +384 256 l +544 256 l +544 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightblue"> +384 256 m +384 224 l +704 224 l +704 256 l +h +</path> +<text matrix="1 0 0 1 45.3282 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="184.702" height="14.9448" depth="0" valign="baseline" size="small">\small Destination Address</text> +<text matrix="1 0 0 1 430.328 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="61.9848" height="14.9448" depth="0" valign="baseline" size="small">\small Source</text> +<text matrix="1 0 0 1 237.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="145.154" height="16.1424" depth="5.376" valign="baseline" size="small">\small Type (0xBEEF)</text> +<text matrix="1 0 0 1 427.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="84.5928" height="14.952" depth="4.176" valign="baseline" size="small">\small RX Flags</text> +<text matrix="1 0 0 1 30.3282 218.732" transformations="translations" pos="96 224" stroke="black" type="label" width="71.9664" height="14.9448" depth="0" valign="baseline" size="small">\small Address</text> +<path matrix="1 0 0 1 -537.672 147.732" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<text matrix="1 0 0 1 -62.672 189.732" transformations="translations" pos="96 224" stroke="black" type="label" width="110.182" height="14.9448" depth="0" valign="baseline" size="small">\small FIFO\_status</text> +<path matrix="1 0 0 1 -377.672 147.732" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<text matrix="1 0 0 1 81.328 192.732" transformations="translations" pos="96 224" stroke="black" type="label" width="52.3516" height="9.7104" depth="2.688" valign="baseline" size="large">\tiny SeqNum</text> +<text matrix="1 0 0 1 175.328 192.732" transformations="translations" pos="96 224" stroke="black" type="label" width="25.2224" height="9.6852" depth="0" valign="baseline" size="large">\tiny rsvd</text> +<path matrix="1 0 0 1 -5 0" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<text matrix="1 0 0 1 358.328 189.732" transformations="translations" pos="96 224" stroke="black" type="label" width="60.7872" height="14.9448" depth="0" valign="baseline" size="small">\small Word0</text> +<path matrix="1 0 0 1 1 242" stroke="black" fill="lightblue" tiling="falling"> +5 63.5079 m +5 46.9999 l +645 46.9999 l +645 63.5079 l +h +</path> +<path matrix="1 0 0 1 262 148" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 81" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 33" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 320 100" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 -320 33" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 -320 33" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<text matrix="1 0 0 1 288 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_0$</text> +<path matrix="1 0 0 1 154 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 315 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -167 -99" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -7 -99" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -167 -147" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -7 -147" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<text matrix="1 0 0 1 371 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_0$</text> +<text matrix="1 0 0 1 446 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_1$</text> +<text matrix="1 0 0 1 529 137" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_1$</text> +<text matrix="1 0 0 1 -32 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_2$</text> +<text matrix="1 0 0 1 51 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_2$</text> +<text matrix="1 0 0 1 128 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_3$</text> +<text matrix="1 0 0 1 211 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_3$</text> +<text matrix="1 0 0 1 -32 22" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_{638}$</text> +<text matrix="1 0 0 1 51 22" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_{638}$</text> +<text matrix="1 0 0 1 128 22" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_{639}$</text> +<text matrix="1 0 0 1 211 22" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_{639}$</text> +<text matrix="1 0 0 1 0 -24" transformations="translations" pos="0 240" stroke="black" type="minipage" width="736" height="65.3664" depth="53.52" valign="top" size="small">\tiny +\begin{itemize} +\item {\bf Type:} 2 byte (16 bit) field that specifies the RoE protocol +\item {\bf RX Flags:} overrun indicator. should be '0'. +\item {\bf FIFO status:} 2 bytes. should be '0'. +\item {\bf SeqNum:} 1 byte. Sequence number of the ethernet packet. +\item {\bf rsvd:} 1 byte. shoult be '0'. \item {\bf Word0:} 4 byte (32-bit). should be '0'. +\item {\bf Timstamp:} Timestamp in samples of the first sample of the received packet. \end{itemize} +\begin{itemize} +\item {\bf data block :} Uncompressed IQ samples, 8-bit resolution for each real and imaginary component. 640 complex samples per packet. +\end{itemize}</text> +<path matrix="1 0 0 1 -377.672 147.732" stroke="black" fill="lightblue"> +384 256 m +384 224 l +704 224 l +704 256 l +h +</path> +<text matrix="1 0 0 1 17.328 157.732" transformations="translations" pos="96 224" stroke="black" type="label" width="103.87" height="14.952" depth="4.176" valign="baseline" size="small">\small Timestamp</text> +<path matrix="1 0 0 1 262 81" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 0 33" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 153 -99" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 313 -99" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<text matrix="1 0 0 1 288 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_4$</text> +<text matrix="1 0 0 1 371 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_4$</text> +<text matrix="1 0 0 1 448 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $I_5$</text> +<text matrix="1 0 0 1 531 70" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="11.856" depth="0" valign="top" size="small">\tiny $Q_5$</text> +<path matrix="1 0 0 1 262.328 128.732" stroke="black" fill="red"> +64 160 m +64 128 l +384 128 l +384 160 l +h +</path> +<text matrix="1 0 0 1 283.328 40.7323" transformations="translations" pos="96 224" stroke="black" type="label" width="214.279" height="14.952" depth="4.176" valign="baseline" size="small">\small Frame Check Sequence</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 185 -0.999076" transformations="translations" pos="176 556" stroke="black" type="label" width="347.724" height="20.9244" depth="6.972" halign="center" valign="baseline">IF4p5 Packet Formats (RAW)</text> +<path stroke="black"> +272 512 m +272 512 l +272 512 l +272 512 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 102 144" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 262 144" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 422 144" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<text matrix="1 0 0 1 -54 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">0</text> +<text matrix="1 0 0 1 106 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">16</text> +<text matrix="1 0 0 1 266 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">32</text> +<text matrix="1 0 0 1 426 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">48</text> +<text matrix="1 0 0 1 73 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">15</text> +<text matrix="1 0 0 1 233 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">31</text> +<text matrix="1 0 0 1 393 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">47</text> +<text matrix="1 0 0 1 553 150" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">63</text> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="violet"> +64 320 m +64 288 l +544 288 l +544 320 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="orange"> +544 320 m +544 288 l +704 288 l +704 320 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="orange"> +64 288 m +64 256 l +384 256 l +384 288 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="lightyellow"> +384 288 m +384 256 l +544 256 l +544 288 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="lightblue"> +384 256 m +384 224 l +704 224 l +704 256 l +h +</path> +<path matrix="1 0 0 1 -58 207" stroke="black" fill="lightblue"> +64 160 m +64 96 l +704 96 l +704 160 l +h +</path> +<text matrix="1 0 0 1 45 215" transformations="translations" pos="96 224" stroke="black" type="label" width="184.702" height="14.9448" depth="0" valign="baseline" size="small">\small Destination Address</text> +<text matrix="1 0 0 1 430 215" transformations="translations" pos="96 224" stroke="black" type="label" width="61.9848" height="14.9448" depth="0" valign="baseline" size="small">\small Source</text> +<text matrix="1 0 0 1 237 186" transformations="translations" pos="96 224" stroke="black" type="label" width="139.111" height="16.1424" depth="5.376" valign="baseline" size="small">\small Type (0x080A)</text> +<text matrix="1 0 0 1 391 186" transformations="translations" pos="96 224" stroke="black" type="label" width="164.63" height="16.1424" depth="5.376" valign="baseline" size="small">\small Subtype (0x0021)</text> +<text matrix="1 0 0 1 30 183" transformations="translations" pos="96 224" stroke="black" type="label" width="71.9664" height="14.9448" depth="0" valign="baseline" size="small">\small Address</text> +<text matrix="1 0 0 1 239 151" transformations="translations" pos="96 224" stroke="black" type="label" width="250.642" height="14.952" depth="4.176" valign="baseline" size="small">\small LTE PRACH Configuration</text> +<text matrix="1 0 0 1 30 151" transformations="translations" pos="96 224" stroke="black" type="label" width="81.4704" height="14.9448" depth="0" valign="baseline" size="small">\small Reserved</text> +<text matrix="1 0 0 1 47 105" transformations="translations" pos="96 224" stroke="black" type="label" width="314.436" height="16.1424" depth="5.376" valign="baseline" size="small">\small PRACH data block (one antenna)</text> +<path matrix="1 0 0 1 -58 144" stroke="black" fill="red"> +64 160 m +64 128 l +384 128 l +384 160 l +h +</path> +<text matrix="1 0 0 1 -53 57" transformations="translations" pos="96 224" stroke="black" type="label" width="214.279" height="14.952" depth="4.176" valign="baseline" size="small">\small Frame Check Sequence</text> +<path matrix="1 0 0 1 -58 144" stroke="black"> +384 160 m +384 128 l +704 128 l +704 160 l +h +</path> +<text matrix="1 0 0 1 -58 118" transformations="translations" pos="64 384" stroke="black" type="label" width="423.247" height="17.9352" depth="5.976" valign="baseline" size="small">IF4p5 PRACH Packet (RRU$\rightarrow$ RAU,RCC)</text> +<text matrix="1 0 0 1 0 27" transformations="translations" pos="0 240" stroke="black" type="minipage" width="736" height="98.2224" depth="86.472" valign="top" size="small">\tiny +\begin{itemize} +\item {\bf Type:} 2 byte (16 bit) field that specifies the RoE protocol +\item {\bf Subtype:} 2 byte (16 bit) field that specifies the packet subtype +\item {\bf Reserved:} 4 byte (32 bit) field reserved +\item {\bf LTE PRACH conf:} 4 byte (32-bit) field that details the configuration of the LTE PRACH packet +\end{itemize} +\vskip 3pt +\begin{tabular}{|c|c|} +\hline +{\bf field (0 is LSB, 31 is MSB)} & {\bf description}\\ \hline +rsvd (0:2) & Reserved.\\ \hline +ant (3:5) & 3-bit Antenna index of LTE PRACH packet\\ \hline +RF Num (6:21) & 16-bit field indicating the Radio Frame number of this received PRACH packet\\ \hline +SF Num (22:25) & 4-bit field indicating the sub-frame number in the radio frame for the LTE PRACH packet\\ + & Valid range of 0 to 9.\\ \hline +Exponent (26:31) & FFT exponent output (0 if unscaled) \\ +\hline +\end{tabular} +\begin{itemize} +\item {\bf PRACH data block:} Uncompressed IQ samples +\end{itemize}</text> +<path matrix="1 0 0 1 -58 -176.508" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 -176.508" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<text matrix="1 0 0 1 -63 -167.508" transformations="translations" pos="96 224" stroke="black" type="label" width="63.5328" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 0 (Real)</text> +<text matrix="1 0 0 1 93 -167.508" transformations="translations" pos="96 224" stroke="black" type="label" width="66.6048" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 0 (Imag)</text> +<text matrix="1 0 0 1 257 -167.508" transformations="translations" pos="96 224" stroke="black" type="label" width="63.5328" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 1 (Real)</text> +<text matrix="1 0 0 1 417 -167.508" transformations="translations" pos="96 224" stroke="black" type="label" width="66.6048" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 1 (Imag)</text> +<path matrix="1 0 0 1 -0.000004 -224.508" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 -0.000004 -224.508" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 -58 -224" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 -224" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<text matrix="1 0 0 1 -63 -215" transformations="translations" pos="96 224" stroke="black" type="label" width="76.236" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 837 (Real)</text> +<text matrix="1 0 0 1 93 -215" transformations="translations" pos="96 224" stroke="black" type="label" width="79.308" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 837 (Imag)</text> +<text matrix="1 0 0 1 257 -215" transformations="translations" pos="96 224" stroke="black" type="label" width="76.236" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 838 (Real)</text> +<text matrix="1 0 0 1 417 -215" transformations="translations" pos="96 224" stroke="black" type="label" width="79.308" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny RE 838 (Imag)</text> +<path matrix="1 0 0 1 -0.000014 -272" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 -0.000014 -272" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path stroke="black" fill="lightblue" tiling="falling"> +6.00001 47.492 m +6.00001 32 l +646 32 l +646 47.492 l +h +</path> +<path stroke="black"> +528 16 m +528 16 l +528 16 l +528 16 l +h +</path> +<path stroke="black"> +560 16 m +560 16 l +560 16 l +560 16 l +h +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +64 224 m +64 192 l +224 192 l +224 224 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +224 224 m +224 192 l +384 192 l +384 224 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +384 224 m +384 192 l +544 192 l +544 224 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +544 224 m +544 192 l +704 192 l +704 224 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +64 192 m +64 160 l +224 160 l +224 192 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +224 192 m +224 160 l +384 160 l +384 192 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +384 192 m +384 160 l +544 160 l +544 192 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +544 192 m +544 160 l +704 160 l +704 192 l +h +</path> +<text matrix="1 0 0 1 -42 155" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 0</text> +<text matrix="1 0 0 1 118 155" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 1</text> +<text matrix="1 0 0 1 -42 123" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 4</text> +<text matrix="1 0 0 1 118 123" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 5</text> +<text matrix="1 0 0 1 278 155" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 2</text> +<text matrix="1 0 0 1 438 155" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 3</text> +<text matrix="1 0 0 1 278 123" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 6</text> +<text matrix="1 0 0 1 438 123" transformations="translations" pos="96 224" stroke="black" type="label" width="60.5064" height="14.9448" depth="0" valign="baseline" size="small">\small Gain 7</text> +<path matrix="1 0 0 1 0 36" stroke="black"> +272 512 m +272 512 l +272 512 l +272 512 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 102 180" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 262 180" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 422 180" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<text matrix="1 0 0 1 -54 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">0</text> +<text matrix="1 0 0 1 106 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">16</text> +<text matrix="1 0 0 1 266 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">32</text> +<text matrix="1 0 0 1 426 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">48</text> +<text matrix="1 0 0 1 73 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">15</text> +<text matrix="1 0 0 1 233 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">31</text> +<text matrix="1 0 0 1 393 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">47</text> +<text matrix="1 0 0 1 553 186" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">63</text> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="violet"> +64 320 m +64 288 l +544 288 l +544 320 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="orange"> +544 320 m +544 288 l +704 288 l +704 320 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="orange"> +64 288 m +64 256 l +384 256 l +384 288 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightyellow"> +384 288 m +384 256 l +544 256 l +544 288 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 180" stroke="black" fill="lightblue"> +384 256 m +384 224 l +704 224 l +704 256 l +h +</path> +<text matrix="1 0 0 1 45 251" transformations="translations" pos="96 224" stroke="black" type="label" width="184.702" height="14.9448" depth="0" valign="baseline" size="small">\small Destination Address</text> +<text matrix="1 0 0 1 430 251" transformations="translations" pos="96 224" stroke="black" type="label" width="61.9848" height="14.9448" depth="0" valign="baseline" size="small">\small Source</text> +<text matrix="1 0 0 1 237 222" transformations="translations" pos="96 224" stroke="black" type="label" width="139.111" height="16.1424" depth="5.376" valign="baseline" size="small">\small Type (0x080A)</text> +<text matrix="1 0 0 1 391 222" transformations="translations" pos="96 224" stroke="black" type="label" width="164.63" height="16.1424" depth="5.376" valign="baseline" size="small">\small Subtype (0x0019)</text> +<text matrix="1 0 0 1 30 219" transformations="translations" pos="96 224" stroke="black" type="label" width="71.9664" height="14.9448" depth="0" valign="baseline" size="small">\small Address</text> +<text matrix="1 0 0 1 239 187" transformations="translations" pos="96 224" stroke="black" type="label" width="119.986" height="14.9448" depth="0" valign="baseline" size="small">\small Frame status</text> +<text matrix="1 0 0 1 30 187" transformations="translations" pos="96 224" stroke="black" type="label" width="81.4704" height="14.9448" depth="0" valign="baseline" size="small">\small Reserved</text> +<path matrix="1 0 0 1 -58 99" stroke="black" fill="red"> +64 160 m +64 128 l +384 128 l +384 160 l +h +</path> +<text matrix="1 0 0 1 -53 12" transformations="translations" pos="96 224" stroke="black" type="label" width="214.279" height="14.952" depth="4.176" valign="baseline" size="small">\small Frame Check Sequence</text> +<text matrix="1 0 0 1 0 -12" transformations="translations" pos="0 240" stroke="black" type="minipage" width="736" height="116.527" depth="104.808" valign="top" size="small">\tiny +\begin{itemize} +\item {\bf Type:} 2 byte (16 bit) field that specifies the RoE protocol +\item {\bf Subtype:} 2 byte (16 bit) field that specifies the packet subtype +\item {\bf Reserved:} 4 byte (32 bit) field reserved +\item {\bf Frame Status:} 4 byte (32 bit) field +\end{itemize} +\vskip 3pt +\begin{tabular}{|c|c|} +\hline +{\bf field (0 is LSB, 31 is MSB)} & {\bf description}\\ \hline +{\bf ant} (0:2) & The number of Antenna Carriers represented in the packet. Antenna numbers \\ +& range from 0 to 7 with valid inputs being 0,1, 3 and 7 (1,2,4,8 antennas)\\ \hline +{\bf ant start} (3:5) & starting antenna number\\ \hline +{\bf RF Num} (6:21) & 16-bit field indicating the Radio Frame number of the UL\_RE samples\\ \hline +{\bf SF Num} (22:25) & 4-bit field indicating the sub-frame number in the radio frame for the UL\_RE samples\\ + & Valid range of 0 to 9.\\ \hline +{\bf Sym Num:} (26:29) & Symbol number. Valid range of 0 to 13. \\ +{\bf rsvd:} (30:31) & reserved\\ +\hline +\end{tabular} +\begin{itemize} +\item {\bf ULRE data block:} compressed IQ samples (8-bit A-law). $N$ is the number of resource elements $N_{\mathrm{RB}}^{\mathrm{UL}}$. +\end{itemize}</text> +<path matrix="1 0 0 1 1 245" stroke="black" fill="lightblue" tiling="falling"> +5 63.5079 m +5 46.9999 l +645 46.9999 l +645 63.5079 l +h +</path> +<path matrix="1 0 0 1 -58 84" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 84" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 36" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 36" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<text matrix="1 0 0 1 38 166" transformations="translations" pos="64 384" stroke="black" type="label" width="589.005" height="25.102" depth="8.372" valign="baseline" size="large">IF4p5 Packets : ULRE (RRU$\rightarrow$ RAU,RCC)</text> +<path matrix="1 0 0 1 0 36" stroke="black"> +256 240 m +256 240 l +256 240 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<path matrix="1 0 0 1 -320.398 35.9995" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black" cap="1"> +258.16 141.771 m +258.16 141.771 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black" cap="1"> +418.597 191.907 m +418.597 191.907 l +</path> +<path matrix="1 0 0 1 0 36" stroke="black" cap="1"> +429.181 79.9357 m +429.181 79.9357 l +</path> +<text matrix="1 0 0 1 -56 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 0\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 24 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 0\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 104 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 1\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 184 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 1\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 264 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 2\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 344 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 2\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 424 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 3\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 504 84" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 3\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 -56 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-4$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 24 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-4$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 104 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-3$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 184 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-3$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 264 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-2$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 344 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-2$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 424 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-1$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 504 36" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-1$\\Ant $R$ (Im)</text> +<path matrix="1 0 0 1 -166 -96" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -6 -96" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 153 -96" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 313 -96" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -166 -144" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -6 -144" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 153 -144" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 313 -144" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 0.328186 35.7323" stroke="black"> +272 512 m +272 512 l +272 512 l +272 512 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 102.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 262.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<path matrix="1 0 0 1 422.328 179.732" stroke="black"> +64 352 m +64 320 l +224 320 l +224 352 l +h +</path> +<text matrix="1 0 0 1 -53.6718 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">0</text> +<text matrix="1 0 0 1 106.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">16</text> +<text matrix="1 0 0 1 266.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">32</text> +<text matrix="1 0 0 1 426.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">48</text> +<text matrix="1 0 0 1 73.3282 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">15</text> +<text matrix="1 0 0 1 233.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">31</text> +<text matrix="1 0 0 1 393.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">47</text> +<text matrix="1 0 0 1 553.328 185.732" transformations="translations" pos="64 336" stroke="black" type="minipage" width="32" height="13.8264" depth="1.848" valign="top" size="small">63</text> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="violet"> +64 320 m +64 288 l +544 288 l +544 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +544 320 m +544 288 l +704 288 l +704 320 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="orange"> +64 288 m +64 256 l +384 256 l +384 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightyellow"> +384 288 m +384 256 l +544 256 l +544 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="darkgray"> +544 288 m +544 256 l +704 256 l +704 288 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -57.6718 179.732" stroke="black" fill="lightblue"> +384 256 m +384 224 l +704 224 l +704 256 l +h +</path> +<text matrix="1 0 0 1 45.3282 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="184.702" height="14.9448" depth="0" valign="baseline" size="small">\small Destination Address</text> +<text matrix="1 0 0 1 430.328 250.732" transformations="translations" pos="96 224" stroke="black" type="label" width="61.9848" height="14.9448" depth="0" valign="baseline" size="small">\small Source</text> +<text matrix="1 0 0 1 237.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="139.111" height="16.1424" depth="5.376" valign="baseline" size="small">\small Type (0x080A)</text> +<text matrix="1 0 0 1 391.328 221.732" transformations="translations" pos="96 224" stroke="black" type="label" width="164.63" height="16.1424" depth="5.376" valign="baseline" size="small">\small Subtype (0x0020)</text> +<text matrix="1 0 0 1 30.3282 218.732" transformations="translations" pos="96 224" stroke="black" type="label" width="71.9664" height="14.9448" depth="0" valign="baseline" size="small">\small Address</text> +<text matrix="1 0 0 1 239.328 186.732" transformations="translations" pos="96 224" stroke="black" type="label" width="119.986" height="14.9448" depth="0" valign="baseline" size="small">\small Frame status</text> +<text matrix="1 0 0 1 30.3282 186.732" transformations="translations" pos="96 224" stroke="black" type="label" width="81.4704" height="14.9448" depth="0" valign="baseline" size="small">\small Reserved</text> +<path matrix="1 0 0 1 -57.6718 162.732" stroke="black" fill="red"> +64 160 m +64 128 l +384 128 l +384 160 l +h +</path> +<text matrix="1 0 0 1 -52.6718 75.7323" transformations="translations" pos="96 224" stroke="black" type="label" width="214.279" height="14.952" depth="4.176" valign="baseline" size="small">\small Frame Check Sequence</text> +<text matrix="1 0 0 1 0.328186 51.7323" transformations="translations" pos="0 240" stroke="black" type="minipage" width="736" height="116.527" depth="104.808" valign="top" size="small">\tiny +\begin{itemize} +\item {\bf Type:} 2 byte (16 bit) field that specifies the RoE protocol +\item {\bf Subtype:} 2 byte (16 bit) field that specifies the packet subtype +\item {\bf Reserved:} 4 byte (32 bit) field reserved +\item {\bf Frame Status:} 4 byte (32 bit) field +\end{itemize} +\vskip 3pt +\begin{tabular}{|c|c|} +\hline +{\bf field (0 is LSB, 31 is MSB)} & {\bf description}\\ \hline +{\bf ant} (0:2) & The number of Antenna Carriers represented in the packet. Antenna numbers \\ +& range from 0 to 7 with valid inputs being 0,1, 3 and 7 (1,2,4,8 antennas)\\ \hline +{\bf ant start} (3:5) & starting antenna number\\ \hline +{\bf RF Num} (6:21) & 16-bit field indicating the Radio Frame number of this DLRE packet\\ \hline +{\bf SF Num} (22:25) & 4-bit field indicating the sub-frame number in the radio frame for the DLRE packet\\ + & Valid range of 0 to 9.\\ \hline +{\bf Sym Num:} (26:29) & Symbol number. Valid range of 0 to 13. \\ +{\bf rsvd:} (30:31) & reserved\\ +\hline +\end{tabular} +\begin{itemize} +\item DLRE data block : compressed IQ samples (8-bit A-law). $N$ is the number of resource elements $N_{\mathrm{RB}}^{\mathrm{DL}}$. +\end{itemize}</text> +<text matrix="1 0 0 1 38.3282 165.732" transformations="translations" pos="64 384" stroke="black" type="label" width="590.262" height="25.102" depth="8.372" valign="baseline" size="large">IF4p5 Packets : DLRE (RAU,RCC $\rightarrow$RRU)</text> +<path matrix="1 0 0 1 0.328186 99.7323" stroke="black" cap="1"> +258.16 141.771 m +258.16 141.771 l +</path> +<path matrix="1 0 0 1 0.328186 99.7323" stroke="black" cap="1"> +418.597 191.907 m +418.597 191.907 l +</path> +<path matrix="1 0 0 1 0.328186 99.7323" stroke="black" cap="1"> +429.181 79.9357 m +429.181 79.9357 l +</path> +<path matrix="1 0 0 1 1 309" stroke="black" fill="lightblue" tiling="falling"> +5 63.5079 m +5 46.9999 l +645 46.9999 l +645 63.5079 l +h +</path> +<path matrix="1 0 0 1 -58 148" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 148" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 262 100" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 -58 100" stroke="black" fill="lightblue"> +64 256 m +64 224 l +384 224 l +384 256 l +h +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +166 304 m +165.917 272.508 l +166.247 272.508 l +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +486 304 m +486.316 272.508 l +485.986 272.508 l +</path> +<path matrix="1 0 0 1 0 100" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<path matrix="1 0 0 1 -320.398 99.9995" stroke="black"> +486.316 256 m +486.646 224 l +485.657 224 l +</path> +<text matrix="1 0 0 1 -56 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 0\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 24 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 0\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 104 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 1\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 184 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 1\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 264 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 2\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 344 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 2\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 424 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 3\\Ant 1 (Re)</text> +<text matrix="1 0 0 1 504 148" transformations="translations" pos="64 256" stroke="black" type="minipage" width="80" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE 3\\Ant 1 (Im)</text> +<text matrix="1 0 0 1 -56 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-4$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 24 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-4$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 104 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-3$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 184 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-3$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 264 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-2$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 344 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-2$\\Ant $R$ (Im)</text> +<text matrix="1 0 0 1 424 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-1$\\Ant $R$ (Re)</text> +<text matrix="1 0 0 1 504 100" transformations="translations" pos="64 256" stroke="black" type="minipage" width="96" height="18.7968" depth="6.84" valign="top" size="small">\tiny RE $N-1$\\Ant $R$ (Im)</text> +<path matrix="1 0 0 1 -166 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -6 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 153 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 313 -32" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -166 -80" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 -6 -80" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 153 -80" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +<path matrix="1 0 0 1 313 -80" stroke="black"> +248.997 435.732 m +248.997 403.732 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" stroke="black" fill="violet"> +640 128 m +640 32 l +704 32 l +704 128 l +h +</path> +<path stroke="black" fill="violet"> +640 480 m +640 176 l +720 176 l +720 480 l +h +</path> +<path matrix="0.782649 0 0 1 194.326 12" fill="lightgray"> +328.159 119.72 m +328.159 15.3556 l +554.022 15.3556 l +554.022 119.72 l +h +</path> +<path matrix="0.898058 0 0 0.385515 103.608 -169.189" fill="lightyellow" fillrule="eofill"> +96 784 m +96 496 l +224 496 l +224 784 l +h +</path> +<path matrix="1 0 0 1 -69 -4" stroke="black"> +-192 928 m +-192 944 l +-192 944 l +-192 928 l +h +</path> +<path matrix="0.956412 0 0 1.08596 98.2256 -362.832" fill="lightyellow"> +96 784 m +96 496 l +224 496 l +224 784 l +h +</path> +<text matrix="1 0 0 1 147 -22" transformations="translations" pos="48 512" stroke="black" type="label" width="124.692" height="14.9448" depth="0" valign="baseline" size="small">\begin{small}L1 Instance 0\end{small}</text> +<text matrix="1 0 0 1 144 -377" transformations="translations" pos="48 512" stroke="black" type="label" width="128.453" height="16.6032" depth="0" valign="baseline" size="small">LI instance 1</text> +<text matrix="1 0 0 1 406 -26" transformations="translations" pos="48 512" stroke="black" type="label" width="270.245" height="16.1424" depth="5.376" valign="baseline" size="small">\begin{small}MAC/RLC/PDCP Instance 0\end{small}</text> +<path matrix="1 0 0 1 -46 -4" stroke="black"> +364 518 m +364 518 l +364 518 l +364 518 l +h +</path> +<path matrix="1.39392 0 0 1.07237 321.184 -356.09" fill="lightgray"> +96 784 m +96 496 l +224 496 l +224 784 l +h +</path> +<path matrix="0.835391 0 0 0.672703 360.137 -36.0947" fill="lightblue"> +128 768 m +128 704 l +192 704 l +192 768 l +h +</path> +<text matrix="1.36111 0 0 0.829268 467.799 77.5985" transformations="translations" pos="0 474" stroke="black" type="minipage" width="52" height="17.6496" depth="5.664" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +DL/UL Scheduler +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 200.75 -1" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 465.792 27.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 250.75 -1" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 393.75 -1" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 653.792 27.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 270.958 48.6756" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 536 76.927" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 320.75 49" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 392.75 49" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 652.792 77.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<path matrix="1 0 0 1 127 14" stroke="blue" arrow="normal/normal"> +180 460 m +340 460 l +</path> +<path matrix="1 0 0 1 127 -13" stroke="red" rarrow="normal/normal"> +180 460 m +340 460 l +</path> +<text matrix="1 0 0 1 152 4" transformations="translations" pos="200 480" stroke="blue" type="minipage" width="128" height="10.128" depth="0" valign="top" size="small">\begin{tiny}1ms TICK\end{tiny}</text> +<path matrix="1 0 0 1 75 -1" stroke="red" arrow="normal/normal"> +392.067 448.35 m +232.502 360 l +</path> +<text matrix="1 0 0 1 87 -9" transformations="translations" pos="230 460" stroke="red" type="label" width="144.917" height="8.3136" depth="3.576" valign="baseline" size="small">\begin{tiny}$\mathrm{DCI}_0$, Transport Blocks\end{tiny} +</text> +<text matrix="0.883494 0.468443 -0.468443 0.883494 345.823 -153.876" pos="230 460" stroke="red" type="label" width="46.6752" height="8.1384" depth="3.576" valign="baseline" size="small">\begin{tiny}$\mathrm{DCI}_1$\end{tiny} +</text> +<text matrix="0.660422 0.750895 -0.750895 0.660422 585.762 -107.641" pos="230 460" stroke="red" type="label" width="46.6752" height="8.1384" depth="3.576" valign="baseline" size="small">\begin{tiny}$\mathrm{DCI}_2$\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 515.792 27.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 585.792 77.2514" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.5 -1" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 29.0442" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.502 -101" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 -70.9558" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_1$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.502 -203.29" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 -173.245" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_2$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.502 49" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 79.0442" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.502 -51" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 -20.9558" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_1$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -547.502 -149" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 200.252 -118.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_2$ +\end{tiny} +</text> +<path matrix="1 0 0 1 75 -1" stroke="blue" arrow="normal/normal"> +234.502 211.006 m +387 210 l +</path> +<path matrix="1 0 0 1 130 -4" stroke="black" cap="1"> +243.386 213.48 m +243.386 213.48 l +</path> +<path matrix="1 0 0 1 75 9" stroke="red" rarrow="normal/normal"> +232.502 250.102 m +387.004 250.371 l +</path> +<path matrix="1 0 0 1 75 -1" stroke="blue" arrow="normal/normal"> +232.502 310 m +387 310 l +</path> +<path matrix="1 0 0 1 75 8" stroke="red" rarrow="normal/normal"> +232.502 346.88 m +387 347 l +</path> +<path matrix="1.06124 0 0 1.05601 109.366 -29.2854" stroke="red" arrow="normal/normal"> +336.917 451.424 m +185.872 274.589 l +</path> +<path matrix="1 0 0 1 75 -1" stroke="blue" arrow="normal/normal"> +232.5 410 m +386.079 409.083 l +</path> +<text matrix="1 0 0 1 132.165 -102.466" transformations="translations" pos="230 460" stroke="red" type="label" width="98.448" height="8.3232" depth="2.304" valign="baseline" size="small">\begin{tiny}Transport Blocks\end{tiny} +</text> +<text matrix="1 0 0 1 131.548 -196.94" transformations="translations" pos="230 460" stroke="red" type="label" width="98.448" height="8.3232" depth="2.304" valign="baseline" size="small">\begin{tiny}Transport Blocks\end{tiny} +</text> +<text matrix="1 0 0 1 117 0" transformations="translations" pos="191.31 225.577" stroke="blue" type="minipage" width="124.891" height="19.9872" depth="8.04" valign="top" size="small">\setstretch{.5}\begin{tiny}CQI/SR/ACK/NAK/PHR\\Transport Blocks\end{tiny}</text> +<text matrix="1 0 0 1 115.548 97.0652" transformations="translations" pos="191.31 225.577" stroke="blue" type="minipage" width="124.891" height="19.9872" depth="8.04" valign="top" size="small">\setstretch{.5}\begin{tiny}CQI/SR/ACK/NAK/PHR\\Transport Blocks\end{tiny}</text> +<text matrix="1 0 0 1 116.852 197.782" transformations="translations" pos="191.31 225.577" stroke="blue" type="minipage" width="124.891" height="19.9872" depth="8.04" valign="top" size="small">\setstretch{.5}\begin{tiny}CQI/SR/ACK/NAK/PHR\\Transport Blocks\end{tiny}</text> +<path matrix="1 0 0 1 123.894 -343.063" stroke="blue" arrow="normal/normal"> +180 460 m +340 460 l +</path> +<path matrix="1 0 0 1 123.894 -370.063" stroke="red" rarrow="normal/normal"> +180 460 m +340 460 l +</path> +<text matrix="1 0 0 1 148.894 -353.063" transformations="translations" pos="200 480" stroke="blue" type="minipage" width="128" height="10.128" depth="0" valign="top" size="small">\begin{tiny}1ms TICK\end{tiny}</text> +<text matrix="1 0 0 1 88.894 -366.063" transformations="translations" pos="230 460" stroke="red" type="label" width="144.917" height="8.3136" depth="3.576" valign="baseline" size="small">\begin{tiny}$\mathrm{DCI}_0$, Transport Blocks\end{tiny} +</text> +<path matrix="1.05698 0 0 1.52948 107.055 -427.707" stroke="blue" arrow="normal/normal"> +184.502 313 m +332 313 l +</path> +<text matrix="1 0 0 1 405.673 -373.496" transformations="translations" pos="48 512" stroke="black" type="label" width="270.245" height="16.1424" depth="5.376" valign="baseline" size="small">\begin{small}MAC/RLC/PDCP Instance 1\end{small}</text> +<path matrix="0.791667 0 0 1 202.166 -54.3244" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 467.208 -26.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 251.958 -54" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 394.958 -54" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 655 -25.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 517 -25.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 202.166 -149.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 467.208 -121.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 251.958 -149" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 394.958 -149" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 655 -120.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 517 -120.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 201.958 -101" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 467 -72.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 251.958 -101" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 394.958 -101" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 655 -72.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 517 -72.7486" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 201.75 -199" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 466.792 -170.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 251.75 -199" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 394.75 -199" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 654.792 -170.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 516.792 -170.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -549.88 -359" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 197.872 -328.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX \\ +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -549.882 -309" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 197.872 -278.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX \\ +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<text matrix="1 0 0 1 114 -159" transformations="translations" pos="191.31 225.577" stroke="blue" type="minipage" width="124.891" height="19.9872" depth="8.04" valign="top" size="small">\setstretch{.5}\begin{tiny}CQI/SR/ACK/NAK/PHR\\Transport Blocks\end{tiny}</text> +<path matrix="0.835391 0 0 0.672703 356.345 -392.095" fill="lightblue"> +128 768 m +128 704 l +192 704 l +192 768 l +h +</path> +<text matrix="1.36111 0 0 0.829268 464.007 -278.401" transformations="translations" pos="0 474" stroke="black" type="minipage" width="52" height="17.6496" depth="5.664" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +DL/UL Scheduler +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 196.958 -357" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 462 -328.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 246.958 -357" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 390.958 -357" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 651 -328.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP RX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 267.166 -307.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 532.208 -279.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC TX +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 316.958 -307" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 389.958 -307" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 650 -278.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="42" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PDCP TX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 512 -328.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC RX +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 582 -278.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC TX +\end{tiny} +</text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="489.023" height="20.9244" depth="6.972" halign="center" valign="baseline">RU/L1 Instances and Component Carriers</text> +<path matrix="0.972035 0 0 0.364588 -79.4938 -158.809" fill="lightyellow" fillrule="eofill"> +96 784 m +96 496 l +224 496 l +224 784 l +h +</path> +<path matrix="0.956412 0 0 1.08596 -77.7744 -362.832" fill="lightyellow"> +96 784 m +96 496 l +224 496 l +224 784 l +h +</path> +<path matrix="1 0 0 1 -222 -4" stroke="black"> +364 518 m +364 518 l +364 518 l +364 518 l +h +</path> +<path matrix="2.25001 0 0 1.17344 -723.502 -213.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 -119.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_3$ +\end{tiny} +</text> +<path matrix="1 0 0 1 0 -1" stroke="black"> +144 480 m +144 32 l +176 32 l +176 480 l +h +</path> +<path stroke="black" cap="1"> +176 432 m +176 432 l +</path> +<path matrix="1 0 0 1 0 -7" stroke="0 0 1"> +192 464 m +176 464 l +</path> +<path stroke="blue" cap="1"> +190.041 464 m +190.041 464 l +</path> +<path stroke="blue" cap="1"> +190.041 464 m +190.041 464 l +</path> +<path matrix="1 0 0 1 0 -105" stroke="0 0 1"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 0 -203" stroke="0 0 1"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 0 -363" stroke="0 0 1"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 -0.041 -55" stroke="red"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 0.918 -156" stroke="red"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 -0.041848 -260.196" stroke="red"> +192 464 m +176 464 l +</path> +<path matrix="1 0 0 1 -0.083 -414" stroke="red"> +192 464 m +176 464 l +</path> +<path matrix="2.25001 0 0 1.17344 -723.502 -21.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 72.544" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_0$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1.17344 -723.502 -85.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 8.544" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_1$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1.17344 -723.502 -149.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 -55.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_2$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1.17344 -723.502 -277.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 -183.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_4$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1.17344 -723.502 -382.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 -288.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_5$ +\end{tiny} +</text> +<path matrix="2.25001 0 0 1.17344 -723.502 -432.245" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 24.252 -337.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_6$ +\end{tiny} +</text> +<path matrix="1 0 0 1 0 3" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -13" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -61" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -77" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -125" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -141" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -189" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -205" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -253" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -269" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -359" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -375" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -406" stroke="0 0 1"> +144 464 m +129.959 464 l +</path> +<path matrix="1 0 0 1 0 -424" stroke="1 0 0"> +144 464 m +129.959 464 l +</path> +<path stroke="black" fill="violet"> +640 400 m +640 400 l +640 400 l +640 400 l +h +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 -512 70" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="267.199" depth="255.84" valign="top" size="small">\small\begin{itemize} +\item {\em Radio Unit} (RU) is +\begin{itemize} +\item an entity managing a set of {\bf physical} antennas. It can have a {\em local RF unit} or {\em remote RF unit} +\item performs precoding of multiple eNB TX streams and OFDM modulation (TX) and demodulation (RX) (part of 36.211) +\end{itemize} +\item {\em L1 Instance} (indexed by {\tt Mod\_id}, or {\tt enb\_mod\_id}) is a separate set of threads and contexts for the eNB/gNB procedures. There is one MAC/RLC entity associated to all :1 component carriers. +\item {\em L1 Component Carrier} (indexed by {\tt CC\_id}) is +\begin{itemize} +\item a software entity managing the L1 procedures (36.213,36.212,36.211) and can act on +\begin{itemize} +\item sectored antenna component +\item Rel10+ component carrier +\item virtual cell for DAS or Massive-MIMO array +\end{itemize} +\item each L1 instance is managed by one or two threads which operate on a subframe (TX and RX) and can have a {\em local RU} or {\em remote RU} +\item if a remote radio unit the eNB performs the 36.213 specifications only (HARQ, etc.) and connects to the remainder via the IF2 midhaul interface. +\end{itemize} +\end{itemize} </text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="489.023" height="20.9244" depth="6.972" halign="center" valign="baseline">RU/L1 Instances and Component Carriers</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="489.023" height="20.9244" depth="6.972" halign="center" valign="baseline">RU/L1 Instances and Component Carriers</text> +<text matrix="1 0 0 1 -512 62" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="252.574" depth="241.176" valign="top" size="small">\small\begin{itemize} +\item RU may have both an {\tt if\_device} for fronthaul and an {\tt rf\_device} for interconnection with a local RF unit +\item if the {\tt rf\_device} is absent, it must have a southbound fronthaul interface (either IF5 or IF4p5) depending on the local processing of the remote RU +\item if the {\tt if\_device} is absent, it must have a southbound RF interface and {\tt rf\_device}. +\item three types of L1 processing are performed by the RU \begin{itemize} +\item subset of common L1 procedures from 36.211 specifications +\item fronthaul compression/decompression +\item framing +\end{itemize} +\item on TX +\begin{itemize} +\item A-law compression for (NGFI\_RAU\_IF4p5, NGFI\_RAU\_IF5) +\item A-law decompression (for NGFI\_RRU\_IF4p5 and NGFI\_RRU\_IF5) +\item OFDM modulation and cyclic prefix insertion (for NGFI\_RRU\_IF4p5,NGFI\_RAU\_IF5,3GPP\_eNodeB\_BBU,3GPP\_eNodeB) +\item Precoding (for NGFI\_RAU\_IF5, NGFI\_RAU\_IF4p5,3GPP\_eNodeB\_BBU,3GPP\_eNodeB) +\end{itemize} +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="489.023" height="20.9244" depth="6.972" halign="center" valign="baseline">RU/L1 Instances and Component Carriers</text> +<text matrix="1 0 0 1 -512 62" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="183.014" depth="171.456" valign="top" size="small">\small\begin{itemize} +\item on RX +\begin{itemize} +\item A-law compression for (NGFI\_RRU\_IF4p5, NGFI\_RRU\_IF5) +\item A-law decompression (for NGFI\_RAU\_IF4p5 and 3GPP\_eNodeB\_BBU) +\item cyclic prefix removal, frequency-shifting, OFDM demodulation, PRACH DFT (for NGFI\_RRU\_IF4p5, NGFI\_RAU\_IF5, 3GPP\_eNodeB\_BBU, 3GPP\_eNodeB) +\end{itemize} +\item On TX path +\begin{itemize} +\item L1 instances/component carriers operate on a set of logical antenna ports (0-3 for TM1-6, 4 for eMBMS, 5 for TM7, 6 for positioning, 7-8 for TM8, etc.) +\item each L1 instance has a list of RUs and the logical antenna ports are mapped to the physical antennas attached to the RUs via the precoding function +\end{itemize} +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 -512 87" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="165.41" depth="153.792" valign="top" size="small">\small\begin{itemize} +\item Example configurations +\begin{itemize} +\item {\em itsolated eNB:} one instance and one or several component carriers (multiple-frequencies or antenna sectors). Potentially multiple radio-units (for CoMP). Here there is a common MACRLC instnance driving multiple L1 procedures +\item {\em indoor DAS system (RCC split with L1/L2 RAU) Multiple layer 2 instances each driving one or more component carriers} here the RAU implements multiple L1/L2 instances and precoding function. Usually with IF2/IF1'' xhaul to RCC or potentially also MAC/RLC in RAU with IF1' xhaul to RCC. +\item {\em massive-MIMO array} same as 2nd indoor DAS system (i.e. integrated L1/L2 RAU with array) +\end{itemize} +\end{itemize} </text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="489.023" height="20.9244" depth="6.972" halign="center" valign="baseline">RU/L1 Instances and Component Carriers</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 -117 31" stroke="black" fill="lightyellow"> +288 384 m +288 96 l +672 96 l +672 384 l +h +</path> +<path matrix="1 0 0 1 -117 119" fill="lightblue"> +301.83 142.941 m +301.83 103.286 l +648 104 l +648 144 l +h +</path> +<path matrix="1.19584 0 0 1.2081 -102.418 -199.483" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -372.028 -59.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 198.792 -187.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1 0 0 1 -117 31" fill="lightblue"> +301.83 142.941 m +301.83 103.286 l +648 104 l +648 144 l +h +</path> +<text matrix="1.12743 0 0 0.829268 277.792 -244.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="162" height="11.4576" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF4p5 / ethernet} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 299 -81.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="48" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY TX (212,213) +\end{tiny} +</text> +<path matrix="1.84415 0 0 0.573526 -364.777 112.325" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 260.792 -43.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.23792 0 0 0.982021 -258.579 37.7599" fill="lightblue"> +389.83 375.941 m +389.83 336.286 l +616 336 l +616 376 l +h +</path> +<text matrix="0.769443 0 0 0.141445 327.792 331.279" transformations="translations" pos="0 474" stroke="black" type="minipage" width="74" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NFGI\_IF1pp / ethernet} +\end{tiny} +</text> +<path matrix="1.88415 0 0 0.573526 -235.977 112.325" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 402.792 -43.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="0.769443 0 0 0.141445 300.792 187.279" transformations="translations" pos="0 474" stroke="black" type="minipage" width="122" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +TX PRECODING\\RX COMBINING +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -284.028 -59.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 286.792 -187.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -196.028 -59.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 374.792 -187.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -108.028 -59.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 462.792 -187.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<text matrix="1 0 0 1 -512 63" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="45.4008" depth="33.504" valign="top" size="small">\small\begin{itemize} +\item Example: RAU with {\tt NGFI\_IF1pp} xhaul (MAC/PHY split) northbound, {\tt NGFI\_IF4p5} fronthaul southbound, 2 vCell logical interfaces (2 L1/L2 instances, or 1 L2 instance and 2 CCs), 4 RRUs with {\tt NGFI\_IF4p5} + +\end{itemize} </text> +<path matrix="1.19584 0 0 1.2081 -166.418 -199.483" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 235 -81.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="48" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY RX (212,213) +\end{tiny} +</text> +<path matrix="1.19584 0 0 1.2081 -22.418 -199.483" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 379 -81.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="48" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY RX (212,213) +\end{tiny} +</text> +<path matrix="1.19584 0 0 1.2081 41.582 -199.483" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 443 -81.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="48" height="24.4656" depth="12.528" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +upper-PHY TX (212,213) +\end{tiny} +</text> +<path matrix="0.734203 0 0 0.68606 60.2968 67.2928" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<path matrix="0.734203 0 0 0.68606 147.297 67.2928" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<path matrix="0.734203 0 0 0.68606 235.297 67.2928" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<path matrix="0.734203 0 0 0.68606 323.297 67.2928" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 197.792 -224.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_0$ +\end{tiny} +</text> +<text matrix="1.12743 0 0 0.829268 283.792 -224.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_1$ +\end{tiny} +</text> +<text matrix="1.12743 0 0 0.829268 373.792 -224.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_2$ +\end{tiny} +</text> +<text matrix="1.12743 0 0 0.829268 460.792 -223.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_3$ +\end{tiny} +</text> +<path matrix="1.16776 0 0 0.634205 24.369 185.93" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 241.792 -63.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<path matrix="1.16776 0 0 0.634205 166.576 185.93" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 383.999 -63.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{eNB}_1$ +\end{tiny} +</text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="247.341" height="20.9244" depth="6.972" halign="center" valign="baseline">RAU Example (DAS)</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" stroke="black" fill="lightyellow"> +168 416 m +168 32 l +576 32 l +576 416 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -375.028 -139.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -380.028 -144.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -28.042 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 -76.042 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 189 -172.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX0 +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -384.028 -149.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 186.792 -277.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1 0 0 1 0 -82" fill="lightblue"> +176 176 m +176 136 l +552 136 l +552 176 l +h +</path> +<text matrix="1.12743 0 0 0.829268 277.792 -317.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="162" height="11.4576" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NGFI\_IF4p5 / ethernet} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 237 -173.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX0 +\end{tiny}</text> +<path fill="lightblue"> +184 360 m +184 336 l +552 336 l +552 360 l +h +</path> +<text matrix="1.12743 0 0 0.829268 329.792 -42.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path fill="lightblue"> +184 408 m +184 368 l +552 368 l +552 408 l +h +</path> +<text matrix="0.769443 0 0 0.141445 295.792 324.279" transformations="translations" pos="0 474" stroke="black" type="minipage" width="130" height="11.4576" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt NGFI\_IF1p / ethernet} +\end{tiny} +</text> +<path matrix="1 0 0 1 0 -82" fill="lightblue"> +184 264 m +184 224 l +552 224 l +552 264 l +h +</path> +<text matrix="0.769443 0 0 0.141445 300.792 105.279" transformations="translations" pos="0 474" stroke="black" type="minipage" width="122" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +TX PRECODING\\RX COMBINING +\end{tiny} +</text> +<text matrix="1 0 0 1 -512 63" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="42.1128" depth="30.216" valign="top" size="small">\small\begin{itemize} +\item Example: massive-MIMO RAU with {\tt NGFI\_IF1p} fronthaul northbound, 8 L1 component carriers,1 L2 instances, many local RRUs with {\tt NGFI\_IF4p5} southbound + +\end{itemize} </text> +<path matrix="1.68745 0 0 0.638421 -279.028 -139.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -284.028 -144.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -288.028 -149.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 282.792 -277.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -183.028 -139.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -188.028 -144.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -192.028 -149.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 378.792 -277.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="1.68745 0 0 0.638421 -87.028 -139.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -92.028 -144.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.68745 0 0 0.638421 -96.028 -149.58" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="1.12743 0 0 0.829268 474.792 -277.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="9.6312" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +{\tt if\_device} +\end{tiny} +</text> +<path matrix="0.791667 0 0 1 67.958 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 19.958 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 285 -172.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX1 +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 333 -173.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX1 +\end{tiny}</text> +<path matrix="0.791667 0 0 1 251.958 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.791667 0 0 1 203.958 -200.324" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 469 -172.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX7 +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 517 -173.073" transformations="translations" pos="0 474" stroke="black" type="minipage" width="32" height="17.2968" depth="5.352" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX7 +\end{tiny}</text> +<path fill="lightblue"> +184 320 m +184 288 l +552 288 l +552 320 l +h +</path> +<text matrix="1.12743 0 0 0.829268 329.792 -84.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +RLC +\end{tiny} +</text> +<path fill="lightblue"> +184 280 m +184 248 l +552 248 l +552 280 l +h +</path> +<text matrix="1.12743 0 0 0.829268 331.792 -123.749" transformations="translations" pos="0 474" stroke="black" type="minipage" width="58" height="10.128" depth="0" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +MAC +\end{tiny} +</text> +<path matrix="1 0 0 1 6 0" stroke="black" dash="dashed"> +376 208 m +448 208 l +</path> +<path matrix="0.993512 0 0 0.664471 1.76482 65.9478" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 188.792 -228.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{eNB}_0$ +\end{tiny} +</text> +<path matrix="0.993512 0 0 0.664471 97.7648 65.9478" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 284.792 -205.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{eNB}_1$ +\end{tiny} +</text> +<path matrix="0.993512 0 0 0.664471 281.765 65.9478" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 468.792 -228.749" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{eNB}_7$ +\end{tiny} +</text> +<path matrix="0.917752 0 0 0.481451 6.3714 0.0229267" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 177.792 -296.724" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="14.9568" depth="2.976" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_{0\cdots 15}$ +\end{tiny} +</text> +<path matrix="0.917752 0 0 0.481451 102.371 0.0229267" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 273.792 -296.724" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="14.9568" depth="2.976" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_{16\cdots 31}$ +\end{tiny} +</text> +<path matrix="0.917752 0 0 0.481451 198.371 0.0229267" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 369.792 -296.724" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="14.9568" depth="2.976" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_{32\cdots 47}$ +\end{tiny} +</text> +<path matrix="0.917752 0 0 0.481451 294.371 0.0229267" stroke="red" dash="dashed"> +184.83 261.941 m +184.83 128 l +272 128 l +272 261.941 l +h +</path> +<text matrix="1.12743 0 0 0.829268 465.792 -296.724" transformations="translations" pos="0 474" stroke="red" type="minipage" width="58" height="14.9568" depth="2.976" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_{48\cdots 63}$ +\end{tiny} +</text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="371.398" height="20.9244" depth="6.972" halign="center" valign="baseline">RAU Example (Massive-MIMO)</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="9.32238 0 0 7.538 -3010.38 -2934.28" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1.42158 0 0 1.03726 -243.165 -111.108" stroke="black" fill="violet"> +232 384 m +232 256 l +543.99 256 l +543.99 384 l +h +</path> +<path matrix="0.99836 0 0 1.3492 -9.1566 -33.1014" stroke="black" fill="gold"> +96 136 m +96 48 l +540 48 l +540 136 l +h +</path> +<path matrix="1 0 0 0.95491 6.23114 90.842" fill="lightgray"> +88 192 m +88 80 l +248 80 l +248 192 l +h +</path> +<path matrix="0.967606 0 0 0.857143 10.0338 -17.5714" fill="lightgray"> +88 192 m +88 80 l +248 80 l +248 192 l +h +</path> +<path matrix="0.459459 0 0 1.28571 41.514 -49.285" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 -512 63" transformations="translations" pos="512 464" stroke="black" type="minipage" width="740" height="114.648" depth="102.936" valign="top" size="small">\small\begin{itemize} +\item IF5 transports packets of size equal to a subframe and corresponding to a 1ms chunk of signal in the time-domain. This is done via the functions send\_if5 and recv\_if5, in the layer1 transport procedures ({\tt openair1/PHY/LTE\_TRANSPORT/if5\_tools.c}). A timestamp is given along with the samples, corresponding to the time (in samples) of the first sample of the packet. +\item each block can be compressed with A-law compression, yielding a compression rate of .5. +\end{itemize} </text> +<text matrix="1 0 0 1 169 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="315.42" height="20.9244" depth="6.972" halign="center" valign="baseline">RU Procedures (NGFI\_IF5)</text> +<path matrix="2.25001 0 0 1 -120.88 -377" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 627.252 -346.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_2$ (211,212) +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -120.502 -228" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 627.252 -197.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_2$ (211,212) +\end{tiny} +</text> +<path matrix="0.876018 0 0 0.636058 450.853 -13.2664" stroke="black"> +144 480 m +144 32 l +176 32 l +176 480 l +h +</path> +<text matrix="0.781914 0 0 0.829268 66.928 -374.838" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_0$ +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 738.691 287.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="0.360709 0 0 1 486.749 -75.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -120.88 -329" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 627.252 -298.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_1$ (211,212) +\end{tiny} +</text> +<path matrix="0.360709 0 0 1 486.749 -27.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -120.88 -281" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 627.252 -250.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_0$ (211,212) +\end{tiny} +</text> +<path matrix="0.360709 0 0 1 486.749 20.663" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -119.035 -179" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 628.719 -148.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_1$ (211,212) +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 740.158 336.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -119.035 -131" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 628.719 -100.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_0$ (211,212) +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 740.158 384.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="1 0 0 1 143.432 -152.618" fill="turquoise"> +132 294 m +132 208 l +384 208 l +384 294 l +h +</path> +<path matrix="1 0 0 1 2 -29" stroke="black" arrow="normal/small"> +144.991 145.396 m +289.432 145.382 l +</path> +<path matrix="1 0 0 1 2 -29" stroke="black" arrow="normal/small"> +144.991 120.982 m +289.432 121.382 l +</path> +<text matrix="1 0 0 1 -447.936 88.75" pos="596 32" stroke="black" type="label" width="131.599" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.rxdata[0]}</text> +<text matrix="1 0 0 1 -446.936 64.75" pos="596 32" stroke="black" type="label" width="144.3" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.rxdata[R-1]}</text> +<path matrix="1 0 0 1 188.432 -100.618" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 213.433 -336.618" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny slot\_fep\_ul\par36.211</text> +<path matrix="0.459459 0 0 1.28571 223.135 -158.904" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<path matrix="1 0 0 1 143.432 -152.618" stroke="black" arrow="normal/tiny"> +184 268 m +196 268 l +</path> +<path matrix="1 0 0 1 143.432 -152.618" stroke="black" arrow="normal/tiny"> +184 244 m +196 244 l +</path> +<text matrix="1 0 0 1 -177.839 90.285" pos="596 32" stroke="black" type="label" width="169.706" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt eNB->common\_vars.rxdataF[0]}</text> +<text matrix="1 0 0 1 -176.839 66.285" pos="596 32" stroke="black" type="label" width="182.407" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt eNB->common\_vars.rxdataF[R-1]}</text> +<path matrix="1.14711 0 0 0.643127 105.368 -57.0842" stroke="black" arrow="normal/small"> +273 269 m +412 268 l +</path> +<path matrix="1 0 0 1 2 -29" stroke="black" arrow="normal/small"> +415.263 120.984 m +575 120.608 l +</path> +<path matrix="0.459459 0 0 1.28571 42.234 -159.285" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="0 1 -1 0 166.559 -528.915" pos="596 32" stroke="black" type="label" width="71.16" height="12.8064" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}^{-1}()$</text> +<path matrix="1 0 0 1 2 -29" stroke="black" arrow="normal/tiny"> +56 128 m +110.531 128.542 l +</path> +<text matrix="1 0 0 1 -591.936 75.75" pos="596 32" stroke="black" type="label" width="105.653" height="8.3016" depth="0" valign="baseline" size="small">\tiny from IF5 {\tt if\_device}</text> +<path matrix="1 0 0 1 248 -71.02" stroke="black"> +680 104 m +680 104 l +680 104 l +680 104 l +h +</path> +<path matrix="0.632607 0 0 0.581545 154.85 73.761" stroke="black" fill="lightgreen"> +544 324 m +544 144 l +576 144 l +576 324 l +h +</path> +<text matrix="0.923166 0 0 0.436636 -9.1365 120.386" transformations="translations" pos="548 304" stroke="black" type="minipage" width="24" height="48.3768" depth="36.504" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny P\\R\\E\\C\\O\\D\\I\\N\\G\\</text> +<path matrix="-1.00596 0 0 0.723429 1093.07 21.2483" stroke="black" fill="white"> +632 360 m +632 188 l +660 188 l +660 360 l +h +</path> +<text matrix="1 0 0 1 -325.616 204.83" pos="596 32" stroke="black" type="label" width="131.599" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.txdata[0]}</text> +<path matrix="-7.98213 0 0 0.926402 6014.38 -11.5901" stroke="black" arrow="normal/tiny"> +700 264 m +735.133 264 l +</path> +<path matrix="-1 0 0 1 1129.13 -52.02" stroke="black" arrow="normal/tiny"> +632 264.556 m +671.833 265 l +</path> +<text matrix="0 1 -1 0 712.677 -464.953" pos="636 280" stroke="black" type="minipage" width="84" height="16.6824" depth="4.704" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny do\_ofdm\_mod\_rt()\par 36.211</text> +<text matrix="0.781914 0 0 0.829268 337.809 -371.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="200.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt openair1/SCHED/ru-procedures.c} +\end{tiny} +</text> +<path matrix="1 0 0 1 2 11" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 1.635 2.903" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 1.635 -5.097" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 1.635 -69.097" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<text matrix="0 1 -1 0 164.559 -406.915" pos="596 32" stroke="black" type="label" width="48.876" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}()$</text> +<text matrix="1 0 0 1 -592.594 184.743" pos="596 32" stroke="black" type="label" width="91.9344" height="8.3016" depth="0" valign="baseline" size="small">\tiny to IF5 {\tt if\_device}</text> +<path matrix="0.179243 0 0 -1.07565 47.9624 469.155" stroke="black" rarrow="normal/tiny"> +56 240 m +356.214 240.281 l +</path> +<path matrix="-8.02443 0 0 0.926402 6046.55 -49.554" stroke="black" arrow="normal/tiny"> +700 264 m +735.133 264 l +</path> +<text matrix="1 0 0 1 -325.616 167.83" pos="596 32" stroke="black" type="label" width="144.3" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.txdata[T-1]}</text> +<text matrix="0.781914 0 0 0.829268 187.809 -330.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="10.6272" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt recv\_IF5()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 192.04 -214.271" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="10.6272" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt send\_IF5()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 445.373 -326.074" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_fep\_full()} +\end{tiny} +</text> +<text matrix="1 0 0 1 212 -261" transformations="translations" pos="176 556" stroke="red" type="label" width="203.946" height="19.3704" depth="0" halign="center" valign="baseline">IF5 RU eNB end </text> +<text matrix="0 1 -1 0 344.559 -523.915" pos="596 32" stroke="black" type="label" width="62.2848" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{7.5kHz}()$</text> +<text matrix="0.781914 0 0 0.829268 86.9372 -348.796" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="10.6272" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 90.7769 -227.271" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread\_asynch\_rxtx()} +\end{tiny} +</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="9.40249 0 0 8.45522 -3042.82 -3293.1" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="0.99836 0 0 3.12886 -15.8426 -122.662" stroke="black" fill="gold"> +96 136 m +96 48 l +540 48 l +540 136 l +h +</path> +<path matrix="1 0 0 1 153.231 103.185" fill="lightgray"> +88 192 m +88 80 l +248 80 l +248 192 l +h +</path> +<path matrix="0.975001 0 0 1.09355 6.19995 -41.9606" fill="lightgray"> +88 192 m +88 80 l +248 80 l +248 192 l +h +</path> +<path matrix="0.459459 0 0 1.28571 286.514 -28.285" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 -512 55" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="86.8968" depth="75.096" valign="top" size="small">\small\begin{itemize} +\item IF4p5 transports packets of size equal to an OFDM symbol (for DLRE and ULRE) indexed by the symbol, subframe and frame number. This is done via the functions send\_if4p5 and recv\_if4p5, in the layer1 transport procedures ({\tt openair1/PHY/LTE\_TRANSPORT/if4\_tools.c}). +\item each block are compressed with A-law compression, yielding a compression rate of .5. +\end{itemize} </text> +<text matrix="1 0 0 1 169 -9" transformations="translations" pos="176 556" stroke="black" type="label" width="343.781" height="20.9244" depth="6.972" halign="center" valign="baseline">RU Procedures (NGFI\_IF4p5)</text> +<path matrix="2.25001 0 0 1 -122.88 -356" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 625.252 -325.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_2$ (211,212) +\end{tiny} +</text> +<path matrix="2.25001 0 0 1 -122.502 -207" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 625.252 -176.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_2$ (211,212) +\end{tiny} +</text> +<path matrix="0.876018 0 0 0.636058 448.853 7.7336" stroke="black"> +144 480 m +144 32 l +176 32 l +176 480 l +h +</path> +<text matrix="0.781914 0 0 0.829268 64.928 -375.838" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_0$ +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 736.691 308.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="0.360709 0 0 1 484.749 -54.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -122.88 -308" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 625.252 -277.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_1$ (211,212) +\end{tiny} +</text> +<path matrix="0.360709 0 0 1 484.749 -6.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -122.88 -260" fill="lightgreen"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 625.252 -229.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY RX $n$\\ +$\mathrm{eNB}_0$ (211,212) +\end{tiny} +</text> +<path matrix="0.360709 0 0 1 484.749 41.663" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -121.035 -158" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 626.719 -127.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_1$ (211,212) +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 738.158 357.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path matrix="2.25001 0 0 1 -121.035 -110" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 626.719 -79.956" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="19.1064" depth="7.128" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +PHY TX $n+4$\\ +$\mathrm{eNB}_0$ (211,212) +\end{tiny} +</text> +<path matrix="-0.360709 0 0 -1 738.158 405.337" stroke="red" rarrow="normal/small"> +371.001 106.337 m +323.502 106.337 l +323.502 106.337 l +</path> +<path stroke="black" arrow="normal/small"> +175.991 137.396 m +575 138.93 l +</path> +<path stroke="black" arrow="normal/small"> +175.991 112.982 m +575 114.329 l +</path> +<path matrix="0.459459 0 0 1.28571 71.234 -138.285" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="0 1 -1 0 195.559 -507.915" pos="596 32" stroke="black" type="label" width="71.16" height="12.8064" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}^{-1}()$</text> +<path stroke="black" arrow="normal/tiny"> +56 120 m +141.531 120.07 l +</path> +<text matrix="1 0 0 1 -593.936 96.75" pos="596 32" stroke="black" type="label" width="118.562" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny from IF4p5 {\tt if\_device}</text> +<path matrix="1 0 0 1 248 -79.02" stroke="black"> +680 104 m +680 104 l +680 104 l +680 104 l +h +</path> +<path matrix="0.632607 0 0 0.581545 152.85 94.761" stroke="black" fill="lightgreen"> +544 324 m +544 144 l +576 144 l +576 324 l +h +</path> +<text matrix="0.923166 0 0 0.436636 -11.1365 141.386" transformations="translations" pos="548 304" stroke="black" type="minipage" width="24" height="48.3768" depth="36.504" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny P\\R\\E\\C\\O\\D\\I\\N\\G\\</text> +<path matrix="-2.98839 0 0 1.00696 2588.86 -11.5723" stroke="black" arrow="normal/tiny"> +700 264 m +735.133 264 l +</path> +<text matrix="0.781914 0 0 0.829268 335.809 -372.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="208.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt openair1/SCHED/ru-procedures.c} +\end{tiny} +</text> +<path matrix="1 0 0 1 0 32" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 -0.365 23.903" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 -0.365 15.903" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<path matrix="1 0 0 1 -0.365 -48.097" stroke="red" rarrow="normal/small"> +517.232 240.387 m +576.078 240 l +576.078 240 l +</path> +<text matrix="0 1 -1 0 409.559 -385.915" pos="596 32" stroke="black" type="label" width="48.876" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}()$</text> +<text matrix="1 0 0 1 -594.594 205.743" pos="596 32" stroke="black" type="label" width="104.844" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny to IF4p5 {\tt if\_device}</text> +<path matrix="1 0 0 1 0 -8" stroke="black" rarrow="normal/tiny"> +56 240 m +356.214 240.281 l +</path> +<path matrix="-2.98839 0 0 1.00696 2589.82 -52.8376" stroke="black" arrow="normal/tiny"> +700 264 m +735.133 264 l +</path> +<text matrix="0.786462 0 0 0.829268 173.831 -335.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt recv\_IF4p5()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 326.04 -198.271" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt send\_IF4p5()} +\end{tiny} +</text> +<text matrix="1 0 0 1 56 -237" transformations="translations" pos="176 556" stroke="red" type="label" width="232.308" height="19.3928" depth="5.404" halign="center" valign="baseline">IF4p5 RU eNB end </text> +<path matrix="0.459459 0 0 0.399205 71.703 -11.0389" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<path stroke="black" arrow="normal/tiny"> +111.191 120.045 m +112 70 l +142 69.9344 l +</path> +<path stroke="black" cap="1"> +-36 68 m +-36 68 l +</path> +<path matrix="1 0 0 1 -0.527 -43.483" stroke="black" arrow="normal/small"> +175.991 112.982 m +575 114.329 l +</path> +<text matrix="1 0 0 1 -343.839 111.285" pos="596 32" stroke="black" type="label" width="169.706" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt eNB->common\_vars.rxdataF[0]}</text> +<text matrix="1 0 0 1 -343.839 87.285" pos="596 32" stroke="black" type="label" width="182.407" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt eNB->common\_vars.rxdataF[R-1]}</text> +<text matrix="1 0 0 1 -343.839 43.285" pos="596 32" stroke="black" type="label" width="207.648" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt eNB->prach\_vars.prachF[0$\cdots$ R-1]}</text> +<text matrix="0.781914 0 0 0.829268 81.3732 -352.933" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="10.6272" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread()} +\end{tiny} +</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="12.8399 0 0 9.34249 -4172.16 -3617.58" fill="lightcyan"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<path matrix="1 0 0 1.01102 0 0.424041" stroke="black" fill="violet"> +232 384 m +232 256 l +543.99 256 l +543.99 384 l +h +</path> +<path matrix="1 0 0 1.04447 0 -2.13433" stroke="black" fill="gold"> +96 136 m +96 48 l +540 48 l +540 136 l +h +</path> +<path matrix="1.1248 0 0 1 74.4712 -158" fill="turquoise"> +132 294 m +132 208 l +384 208 l +384 294 l +h +</path> +<path fill="lightyellow"> +96 384 m +96 148 l +544 148 l +544 256 l +224 256 l +224 384 l +h +</path> +<path matrix="1 0 0 1.17279 1 166.419" fill="lightgray"> +444 164 m +444 84.382 l +522.222 84.382 l +522.222 164 l +h +</path> +<path matrix="1 0 0 1 143.432 -48.618" fill="turquoise"> +132 294 m +132 208 l +384 208 l +384 294 l +h +</path> +<path matrix="1 0 0 1 2 77" fill="lightgray"> +444 164 m +444 84.382 l +522.222 84.382 l +522.222 164 l +h +</path> +<path matrix="0.459459 0 0 1.28571 379.514 54.715" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 161 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="343.781" height="20.9244" depth="6.972" halign="center" valign="baseline">RU Procedures (NGFI\_IF4p5)</text> +<text matrix="0.781914 0 0 0.829268 67.928 -354.838" transformations="translations" pos="0 474" stroke="black" type="minipage" width="102" height="11.8344" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +$\mathrm{RU}_0$ +\end{tiny} +</text> +<path matrix="1 0 0 1 2 75" stroke="black" arrow="normal/tiny"> +144.991 145.396 m +289.432 145.382 l +</path> +<path matrix="1 0 0 1 2 75" stroke="black" arrow="normal/tiny"> +144.991 120.982 m +289.432 121.382 l +</path> +<text matrix="1 0 0 1 -447.936 192.75" pos="596 32" stroke="black" type="label" width="131.599" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.rxdata[0]}</text> +<text matrix="1 0 0 1 -446.936 168.75" pos="596 32" stroke="black" type="label" width="144.3" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.rxdata[R-1]}</text> +<path matrix="1 0 0 1 188.432 3.382" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 213.433 -232.618" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny slot\_fep\_ul\par36.211</text> +<path matrix="0.459459 0 0 1.28571 223.135 -54.904" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<path matrix="1 0 0 1 143.432 -48.618" stroke="black" arrow="normal/tiny"> +184 268 m +196 268 l +</path> +<path matrix="1 0 0 1 143.432 -48.618" stroke="black" arrow="normal/tiny"> +184 244 m +196 244 l +</path> +<path matrix="0.248499 0 0 0.662073 349.697 42.5354" stroke="black" arrow="normal/small"> +273 269 m +412 268 l +</path> +<path matrix="0.21663 0 0 1.02946 327.304 71.447" stroke="black" arrow="normal/small"> +415.263 120.984 m +575 120.608 l +</path> +<path matrix="1 0 0 1 2 75" stroke="black" arrow="normal/tiny"> +56 128 m +110.531 128.542 l +</path> +<text matrix="1 0 0 1 -591.936 179.75" pos="596 32" stroke="black" type="label" width="84.276" height="8.3016" depth="0" valign="baseline" size="small">\tiny from {\tt rf\_device}</text> +<path matrix="1 0 0 1 240 -71.02" stroke="black"> +680 104 m +680 104 l +680 104 l +680 104 l +h +</path> +<path matrix="-1.00596 0 0 0.723429 1044.07 125.248" stroke="black" fill="white"> +632 360 m +632 188 l +660 188 l +660 360 l +h +</path> +<text matrix="1 0 0 1 -352.616 267.83" pos="596 32" stroke="black" type="label" width="131.599" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.txdata[0]}</text> +<path stroke="black" arrow="normal/tiny"> +380.13 336.98 m +149.46 336.349 l +</path> +<path matrix="-1 0 0 1 1080.13 51.98" stroke="black" arrow="normal/tiny"> +632 264.556 m +671.833 265 l +</path> +<text matrix="0 1 -1 0 663.677 -360.953" pos="636 280" stroke="black" type="minipage" width="84" height="16.6824" depth="4.704" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny do\_ofdm\_mod\_rt()\par 36.211</text> +<text matrix="0.781914 0 0 0.829268 510.809 -351.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="200.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt openair1/SCHED/ru-procedures.c} +\end{tiny} +</text> +<text matrix="1 0 0 1 -592.594 288.743" pos="596 32" stroke="black" type="label" width="70.5552" height="7.3056" depth="0" valign="baseline" size="small">\tiny to {\tt rf\_device}</text> +<path matrix="1 0 0 1 0 75" stroke="black" rarrow="normal/tiny"> +58 240 m +114.121 240.053 l +</path> +<path stroke="black" arrow="normal/tiny"> +380.45 296 m +149.46 295.058 l +</path> +<text matrix="1 0 0 1 -362.967 310.18" pos="596 32" stroke="black" type="label" width="144.3" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt RU->ru\_time.txdata[T-1]}</text> +<text matrix="0.781914 0 0 0.829268 278.373 -223.074" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_fep\_full()} +\end{tiny} +</text> +<text matrix="1 0 0 1 -5 -65" transformations="translations" pos="176 556" stroke="red" type="label" width="262.063" height="19.3928" depth="5.404" halign="center" valign="baseline">IF4p5 RU remote-end </text> +<path matrix="0.459459 0 0 1.28571 44.014 -55.285" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="0 1 -1 0 502.559 -313.915" pos="596 32" stroke="black" type="label" width="71.16" height="12.8064" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}^{-1}()$</text> +<path matrix="0.45771 0 0 1.1354 381.353 -25.8312" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="0 1 -1 0 504.559 -414.915" pos="596 32" stroke="black" type="label" width="48.876" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{Alaw}()$</text> +<text matrix="0 1 -1 0 345.559 -418.915" pos="596 32" stroke="black" type="label" width="62.2848" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny $\mathrm{7.5kHz}()$</text> +<path matrix="0.459459 0 0 1.28571 44.703 54.165" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="0.781914 0 0 0.829268 449.809 -118.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt recv\_IF4p5()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 450.012 -220.947" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt send\_IF4p5()} +\end{tiny} +</text> +<path matrix="1 0 0 1 0 75" stroke="black" arrow="normal/tiny"> +485.71 128.939 m +581.963 129.331 l +</path> +<text matrix="1 0 0 1 -46.936 178.75" pos="596 32" stroke="black" type="label" width="70.5552" height="7.3056" depth="0" valign="baseline" size="small">\tiny to {\tt if\_device}</text> +<text matrix="1 0 0 1 -46.372 286.887" pos="596 32" stroke="black" type="label" width="84.276" height="8.3016" depth="0" valign="baseline" size="small">\tiny from {\tt if\_device}</text> +<path matrix="1 0 0 1 465.222 73.1439" stroke="black" rarrow="normal/tiny"> +58 240 m +114.121 240.053 l +</path> +<path matrix="1 0 0 1 105.674 -234" stroke="black" fill="1"> +131 344 m +131 316 l +276 316 l +276 344 l +h +</path> +<text matrix="1 0 0 1 123.675 -345" transformations="translations" pos="128 440" stroke="black" type="minipage" width="126.578" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ru\_prach\_procedures\par36.211</text> +<path matrix="1 0 0 1 -58.326 -234" stroke="black" arrow="normal/tiny"> +440.514 328 m +477 327.572 l +</path> +<text matrix="0.762991 0 0 1 1.41573 -218" transformations="translations" pos="300 280" stroke="black" type="minipage" width="268" height="11.4576" depth="0" valign="top" size="small">\tt\tiny ru\_prach\_procedures()</text> +<path matrix="1 0 0 1 267.865 -110" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 292.866 -346" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_prachl\par36.211</text> +<path stroke="black" arrow="normal/tiny"> +199.412 220.391 m +200 104 l +236.674 103.978 l +</path> +<path stroke="black" arrow="normal/tiny"> +178.262 196.069 m +179.06 92 l +236.674 91.6468 l +</path> +<path stroke="black" fill="gold"> +65.0054 121.159 m +65.0054 121.159 l +65.0054 121.159 l +65.0054 121.159 l +h +</path> +<text matrix="0.781914 0 0 0.829268 98.1012 -330.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread\_prach()} +\end{tiny} +</text> +<text matrix="0.781914 0 0 0.829268 99.672 -232.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="10.6272" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread()} +\end{tiny} +</text> +<path stroke="black" fill="violet"> +65.0054 357.66 m +65.0054 357.66 l +65.0054 357.66 l +65.0054 357.66 l +h +</path> +<text matrix="0.781914 0 0 0.829268 234.605 -119.456" transformations="translations" pos="0 474" stroke="black" type="minipage" width="168.119" height="11.4576" depth="0" valign="top" size="small">\setstretch{.5}\begin{tiny} +{\tt ru\_thread\_asynch\_rxtx()} +\end{tiny} +</text> +<text matrix="1 0 0 1 -39.936 67.75" pos="596 32" stroke="black" type="label" width="70.5552" height="7.3056" depth="0" valign="baseline" size="small">\tiny to {\tt if\_device}</text> +<path matrix="1 0 0 1 9.642 -35.284" stroke="black" arrow="normal/tiny"> +485.71 128.939 m +581.963 129.331 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 9.83755 0" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="1 0 0 1 161 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="231.997" height="19.3928" depth="5.404" halign="center" valign="baseline">OAI IF1pp Interface</text> +<text matrix="1 0 0 1 -512 55" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="30.296" depth="16.352" valign="top">\tiny\begin{itemize} +\item OAI IF1pp is the interface between the 36.213 Physical Layer Procedures (HARQ, SR, CSI, etc.) and the transport/physical channel processing +\item it can be networked, although this is not used as an xhaul interface at the moment. +\end{itemize} </text> +<path matrix="1 0 0 1 32 60" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="1 0 0 1 32 60" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<path matrix="1 0 0 1 288 60" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 -399.345 376.743" pos="596 32" stroke="black" type="label" width="151.668" height="7.3224" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_procedures\_lte\_eNB\_TX}</text> +<text matrix="1 0 0 1 -140.021 376.743" pos="596 32" stroke="black" type="label" width="151.668" height="7.3224" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_procedures\_lte\_eNB\_RX}</text> +<path matrix="1 0 0 1 33 -256" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -414.345 60.743" pos="596 32" stroke="black" type="label" width="439.776" height="14.952" depth="4.176" valign="baseline" size="small">\small PHY transport and physical channel procedures</text> +<text matrix="0 1 -1 0 208.848 -455.114" pos="596 32" stroke="black" type="label" width="161.575" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt common\_signal\_procedures()}</text> +<text matrix="0 1 -1 0 232.621 -455.114" pos="596 32" stroke="black" type="label" width="106.193" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt pmch\_procedures()}</text> +<text matrix="0 1 -1 0 256.394 -455.114" pos="596 32" stroke="black" type="label" width="221.532" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt generate\_dlsch\_parameters\_from\_dci()}</text> +<text matrix="0 1 -1 0 280.167 -455.114" pos="596 32" stroke="black" type="label" width="221.532" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt generate\_ulsch\_parameters\_from\_dci()}</text> +<text matrix="0 1 -1 0 303.94 -455.114" pos="596 32" stroke="black" type="label" width="172.5" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_dedicated\_step2()}</text> +<text matrix="0 1 -1 0 327.713 -455.114" pos="596 32" stroke="black" type="label" width="110.765" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt generate\_dci\_top()}</text> +<text matrix="0 1 -1 0 351.486 -455.114" pos="596 32" stroke="black" type="label" width="123.468" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt generate\_phich\_top()}</text> +<text matrix="0 1 -1 0 375.259 -455.114" pos="596 32" stroke="black" type="label" width="112.543" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt pdsch\_procedures()}</text> +<path matrix="1 0 0 1 33.6108 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 57.3839 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 81.1569 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 104.93 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 128.703 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 152.476 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 176.249 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 1 265.346 -0.419" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 464.848 -455.114" pos="596 32" stroke="black" type="label" width="112.543" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt pucch\_procedures()}</text> +<text matrix="0 1 -1 0 487.637 -455.114" pos="596 32" stroke="black" type="label" width="87.1392" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt process\_Msg3()}</text> +<path matrix="1 0 0 1 288.134 0.491" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 511.251 -455.114" pos="596 32" stroke="black" type="label" width="61.7352" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt rx\_ulsch()}</text> +<path matrix="1 0 0 1 310.923 0.509" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 533.214 -455.114" pos="596 32" stroke="black" type="label" width="99.8424" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt ulsch\_decoding()}</text> +<path matrix="1 0 0 1 333.711 0.608" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 556.002 -455.114" pos="596 32" stroke="black" type="label" width="80.7888" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt extract\_cqi()}</text> +<path matrix="1 0 0 1 356.5 0.411" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 578.791 -455.114" pos="596 32" stroke="black" type="label" width="121.69" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt get\_Msg3\_alloc\_ret()}</text> +<path matrix="1 0 0 1 379.288 0.924" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 601.579 -455.114" pos="596 32" stroke="black" type="label" width="183.425" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt lte\_est\_timing\_advance\_pusch()}</text> +<path matrix="1 0 0 1 402.077 1.339" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 625.193 -455.114" pos="596 32" stroke="black" type="label" width="153.446" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt lte\_eNB\_I0\_measurements()}</text> +<path matrix="1 0 0 1 424.865 1.187" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 647.156 -455.114" pos="596 32" stroke="black" type="label" width="117.118" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt process\_HARQ\_info()}</text> +<path matrix="1 0 0 1 447.654 1.187" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="1 0 0 1 16 -48" transformations="translations" pos="0 448" stroke="black" type="minipage" width="128" height="28.0824" depth="16.152" valign="top" size="small">\small {\tt 36.213}\par +{\tt openair1/SCHED}</text> +<text matrix="1 0 0 1 1 -368" transformations="translations" pos="0 448" stroke="black" type="minipage" width="128" height="28.9872" depth="17.04" valign="top" size="small">\small {\tt 36.211/212}\par +{\tt openair1/PHY}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 0 -1" fill="lightgray"> +120 528 m +120 0 l +592 0 l +592 528 l +h +</path> +<path fill="turquoise"> +180 524 m +180 476 l +588 476 l +588 524 l +h +</path> +<path matrix="1 0 0 1 0 5" stroke="black" fill="white"> +248 520 m +248 483.903 l +400 484 l +400 520 l +h +</path> +<path matrix="1 0 0 1 0 -19" fill="lightcyan"> +180 493.216 m +180 452 l +536 452 l +536 493.216 l +h +</path> +<path matrix="1 0 0 1 0 -19" stroke="black"> +404 480 m +404 472 l +404 472 l +404 480 l +h +</path> +<path matrix="1 0 0 1 0 -19" fill="white"> +340 488 m +340 464 l +444 464 l +444 488 l +h +</path> +<path matrix="1 0 0 1 20.9996 13.2948" stroke="black" fill="1"> +312 456 m +312 432 l +424 432 l +424.001 456 l +h +</path> +<path matrix="1 0 0 1 1 -19" fill="lightgreen"> +144 448 m +144 360 l +536 360 l +536 448 l +h +</path> +<path matrix="1 0 0 1 1 -15" fill="lightblue"> +144 260 m +144 116 l +536 116 l +536 260 l +h +</path> +<path matrix="1 0 0 1 1 -16" fill="lightblue"> +144 344 m +144 264 l +536 264 l +536 344 l +h +</path> +<path matrix="1.16667 0 0 1 7.66667 -19" stroke="black" fill="white"> +128 440 m +128 384 l +224 384 l +224 440 l +h +</path> +<text matrix="1 0 0 1 30 -41.7052" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="14.484" depth="2.52" valign="center" size="small">\tt\tiny generate\_dci\_top()</text> +<text matrix="1 0 0 1 -15 -15" transformations="translations" pos="240 144" stroke="black" type="minipage" width="8" height="5.9784" depth="0" valign="top" size="small"></text> +<path fill="gold" tiling="rising"> +0 424 m +0 32 l +48 32 l +48 424 l +h +</path> +<text matrix="1 0 0 1 -17 -127" transformations="translations" pos="32 416" stroke="black" type="minipage" width="32" height="50.1172" depth="36.204" valign="top" style="center">M\\ +A\\ +C</text> +<path matrix="1 0 0 1 -16 -21" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<text matrix="1 0 0 1 -16 -21" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.3664" depth="1.372" valign="top">\tt\tiny DCI\_PDU</text> +<path matrix="1.16667 0 0 1 7.6667 -120" stroke="black" fill="1"> +128 440 m +128 384 l +224 384 l +224 440 l +h +</path> +<text matrix="1 0 0 1 37.0006 -148" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_coding()\par36.212</text> +<path matrix="1 0 0 1 -16 -123" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<text matrix="1 0 0 1 -16 -123" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.3664" depth="1.372" valign="top">\tt\tiny DLSCH\_PDU\_0</text> +<path matrix="1.16667 0 0 1 7.6667 -199" stroke="black" fill="1"> +128 440 m +128 384 l +224 384 l +224 440 l +h +</path> +<path matrix="1 0 0 1 -16 -203" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<text matrix="1 0 0 1 -16 -203" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.3664" depth="1.372" valign="top">\tt\tiny DLSCH\_PDU\_1\_0</text> +<path matrix="1.16667 0 0 1 7.6667 -263" stroke="black" fill="1"> +128 440 m +128 384 l +224 384 l +224 440 l +h +</path> +<path matrix="1 0 0 1 -16 -266" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<text matrix="1 0 0 1 -16 -266" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.3664" depth="1.372" valign="top">\tt\tiny DLSCH\_PDU\_1\_1</text> +<path matrix="1 0 0 1 -18.0004 -34.7052" stroke="black" fill="1"> +312 456 m +312 432 l +424 432 l +424.001 456 l +h +</path> +<text matrix="1 0 0 1 166 -30.7052" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="17.1312" depth="5.184" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny generate\_pcfich()\par36.212,36.211</text> +<path matrix="1 0 0 1 -9 -19" stroke="black" fill="1"> +304 408 m +304 384 l +400 384 l +400 408 l +h +</path> +<text matrix="1 0 0 1 167 -63.2264" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny generate\_dci0()\par36.212</text> +<path matrix="1 0 0 1 1 2.77362" stroke="black" fill="1"> +408 400 m +408 352 l +520 352 l +520 400 l +h +</path> +<text matrix="1 0 0 1 281 -61.2264" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="29.8512" depth="17.904" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny pdcch\_scrambling()\par pdcch\_modulation\par pdcch\_interleaving\par36.211</text> +<text matrix="1 0 0 1 37.0006 -227" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_coding()\par36.212</text> +<text matrix="1 0 0 1 37.0006 -291" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_coding()\par36.212</text> +<path matrix="1 0 0 1 1 -19" stroke="black" fill="white" arrow="normal/tiny"> +268 426.729 m +293 426.729 l +</path> +<path matrix="1 0 0 1 1 -21.3964" stroke="black" fill="white" arrow="normal/tiny"> +268 399.17 m +293 399.17 l +</path> +<path matrix="1 0 0 1 -14 -18.5991" stroke="black" fill="white" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<path matrix="1 0 0 1 1 -17" stroke="black" fill="1"> +294 320 m +294 296 l +392 296 l +392 320 l +h +</path> +<text matrix="1.16993 0 0 1 145.249 -149.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_encoding()\par36.212</text> +<path matrix="1 0 0 1 1 -107.396" stroke="black" arrow="normal/tiny"> +268 399.17 m +293 399.17 l +</path> +<path matrix="1 0 0 1 1 -14" stroke="black" fill="1"> +408 322.774 m +408 288 l +520 288 l +520 322.774 l +h +</path> +<text matrix="1 0 0 1 281 -147.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="23.3352" depth="11.4" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_scrambling()\par dlsch\_modulation()\par36.211</text> +<path matrix="1 0 0 1 -12 -105.599" stroke="black" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<path matrix="1 0 0 1 1 -95" stroke="black" fill="1"> +294 320 m +294 296 l +392 296 l +392 320 l +h +</path> +<text matrix="1.16993 0 0 1 145.249 -227.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_encoding()\par36.212</text> +<path matrix="1 0 0 1 1 -14.726" stroke="black" fill="1"> +408 251 m +408 144 l +520 144 l +520 251 l +h +</path> +<text matrix="1 0 0 1 281 -257.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="30.0144" depth="18.072" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_scrambling()\par dlsch\_modulation()\par[2-4 layers]\par 36.211</text> +<path matrix="1 0 0 1 -12 -183.599" stroke="black" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<path matrix="1 0 0 1 1 -159" stroke="black" fill="1"> +294 320 m +294 296 l +392 296 l +392 320 l +h +</path> +<text matrix="1.16993 0 0 1 145.249 -291.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_encoding()\par36.212</text> +<path matrix="1 0 0 1 -12 -247.599" stroke="black" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<path matrix="1 0 0 1 1 -187.396" stroke="black" arrow="normal/tiny"> +268 399.17 m +293 399.17 l +</path> +<path matrix="1 0 0 1 1 -251.396" stroke="black" arrow="normal/tiny"> +268 399.17 m +293 399.17 l +</path> +<path matrix="1 0 0 1 1 -19" stroke="black" cap="1"> +552 428 m +552 428 l +</path> +<path stroke="black" arrow="normal/tiny"> +405 409 m +600 408.924 l +</path> +<path stroke="black" arrow="normal/tiny"> +520 381 m +600 380.885 l +</path> +<path stroke="black" arrow="normal/tiny"> +521 292.923 m +600 293.648 l +</path> +<text matrix="1 0 0 1 -124 -14" transformations="translations" pos="300 280" stroke="black" type="minipage" width="360.737" height="14.484" depth="2.52" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:pdsch\_procedures()</text> +<text matrix="1 0 0 1 -124 -162" transformations="translations" pos="300 280" stroke="black" type="minipage" width="359.972" height="14.484" depth="2.52" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:pdsch\_procedures()</text> +<text matrix="1 0 0 1 1 -19" transformations="translations" pos="168 372" stroke="black" type="minipage" width="364" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/PHY/LTE\_TRANSPORT/dci.c</text> +<path matrix="1 0 0 1 0 -9" stroke="black"> +360 104 m +360 104 l +360 104 l +360 104 l +h +</path> +<path matrix="1 0 0 1 1 -249" fill="pink"> +144 344 m +144 264 l +536 264 l +536 344 l +h +</path> +<path matrix="1.16667 0 0 1 7.6667 -354" stroke="black" fill="1"> +128 440 m +128 384 l +224 384 l +224 440 l +h +</path> +<text matrix="1 0 0 1 37.0006 -382" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_coding()\par36.212</text> +<text matrix="1 0 0 1 -16 -353" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.3664" depth="1.372" valign="top">\tt\tiny MCH\_PDU</text> +<path matrix="1 0 0 1 1 -251" stroke="black" fill="1"> +294 320 m +294 296 l +392 296 l +392 320 l +h +</path> +<text matrix="1.16993 0 0 1 145.249 -383.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_encoding()\par36.212</text> +<path matrix="1 0 0 1 1 -341.396" stroke="black" arrow="normal/tiny"> +268 399.17 m +293 399.17 l +</path> +<path matrix="1 0 0 1 1 -248" stroke="black" fill="1"> +408 322.774 m +408 288 l +520 288 l +520 322.774 l +h +</path> +<text matrix="1 0 0 1 281 -381.226" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="23.3352" depth="11.4" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny dlsch\_scrambling()\par mch\_modulation()\par36.211</text> +<path matrix="1 0 0 1 -12 -339.599" stroke="black" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<text matrix="1 0 0 1 -124 -251" transformations="translations" pos="300 280" stroke="black" type="minipage" width="360.737" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:pmch\_procedures()</text> +<path matrix="1 0 0 1 -16 -358" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<path matrix="1 0 0 1 0 -10" stroke="black" fill="white"> +128 488 m +128 452 l +172 452 l +172 488 l +h +</path> +<path matrix="1 0 0 1 0 -10" stroke="black"> +140 472 m +140 472 l +140 472 l +140 472 l +h +</path> +<text matrix="1 0 0 1 0 -3" transformations="translations" pos="128 476" stroke="black" type="minipage" width="44" height="19.332" depth="7.368" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny UL CNTL\\36.213</text> +<path matrix="1 0 0 1 0 -10" stroke="black" fill="white"> +188 476 m +188 460 l +316 460 l +316 476 l +h +</path> +<text matrix="1 0 0 1 63 18.2948" transformations="translations" pos="128 440" stroke="black" type="minipage" width="128" height="11.4576" depth="0" valign="center" size="small">\tt\tiny generate\_phich\_top()</text> +<path matrix="1 0 0 1 0 -10" stroke="black" arrow="normal/tiny"> +172 468 m +188 468 l +</path> +<text matrix="1 0 0 1 206 17.2948" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="17.1312" depth="5.184" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny generate\_phich()\par36.212,36.211</text> +<path matrix="1 0 0 1 -88 60.401" stroke="black" arrow="normal/tiny"> +405 397.373 m +421 397.373 l +</path> +<path stroke="black" arrow="normal/tiny"> +445 457 m +600 456.672 l +</path> +<path stroke="black" arrow="normal/tiny"> +520.262 58 m +600 58.7558 l +</path> +<text matrix="1 0 0 1 40 70" transformations="translations" pos="168 372" stroke="black" type="minipage" width="364" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/PHY/LTE\_TRANSPORT/phich.c</text> +<text matrix="1 0 0 1 51 -27" transformations="translations" pos="468 488" stroke="black" type="label" width="62.6328" height="8.3016" depth="0" valign="baseline" size="small">\tiny PHICH REs</text> +<text matrix="1 0 0 1 51 -75" transformations="translations" pos="468 488" stroke="black" type="label" width="69.0456" height="8.3016" depth="0" valign="baseline" size="small">\tiny PCFICH REs</text> +<text matrix="1 0 0 1 55 -105" transformations="translations" pos="468 488" stroke="black" type="label" width="67.428" height="8.3016" depth="0" valign="baseline" size="small">\tiny PDCCH REs</text> +<text matrix="1 0 0 1 38 -160" transformations="translations" pos="468 488" stroke="black" type="label" width="66.3696" height="8.3016" depth="0" valign="baseline" size="small">\tiny PDSCH REs</text> +<path matrix="0.0772642 0 0 0.976417 547.24 -8.88888" stroke="black"> +104.077 0 0 104.077 528 236 e +</path> +<text matrix="1 0 0 1 55 -426" transformations="translations" pos="468 488" stroke="black" type="label" width="61.2216" height="8.3016" depth="0" valign="baseline" size="small">\tiny PMCH REs</text> +<text matrix="1 0 0 1 126.793 67.9996" transformations="translations" pos="128 440" stroke="black" type="minipage" width="112" height="24.18" depth="12.216" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny generate\_pilots\_slot()\par generate\_pss/sss/pbch()\par36.211</text> +<path stroke="black"> +248 488.695 m +248 488.695 l +248 488.695 l +248 488.695 l +h +</path> +<text matrix="1 0 0 1 -120 208" transformations="translations" pos="300 280" stroke="black" type="minipage" width="428" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:common\_signal\_procedures()</text> +<path stroke="black" arrow="normal/tiny"> +401 507 m +600.424 507.963 l +</path> +<text matrix="1 0 0 1 -41 21" transformations="translations" pos="468 488" stroke="black" type="label" width="155.743" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny CS-RS/PSS/SSS/PBCH REs</text> +<path matrix="1 0 0 1 -8 -7" stroke="black" arrow="normal/tiny"> +576 332 m +592 324 l +</path> +<text matrix="1 0 0 1 -97 -262" transformations="translations" pos="300 280" stroke="black" type="minipage" width="387.452" height="14.484" depth="2.52" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:phy\_procedures\_eNB\_TX()</text> +<text matrix="1 0 0 1 191 4" transformations="translations" pos="176 556" stroke="black" type="label" width="235.25" height="19.3704" depth="0" halign="center" valign="baseline">eNB TX Procedures</text> +<text matrix="1 0 0 1 -484 12" transformations="translations" pos="608 516" stroke="black" type="minipage" width="96" height="18.468" depth="6.504" valign="top" size="small">\tiny eNodeB\_3GPP or NGFI\_RCC\_IF4p5</text> +<path matrix="1 0 0 1 -101 288" fill="red"> +232 276 m +232 240 l +240 240 l +240 276 l +h +</path> +<text matrix="1.34783 0 0 1 -218.435 173" transformations="translations" pos="168 372" stroke="black" type="minipage" width="124" height="10.9584" depth="0" valign="top" size="small">\tt\tiny IF2 split points</text> +<path matrix="1 0 0 10.3333 -185 -2439" fill="red"> +232 276 m +232 240 l +240 240 l +240 276 l +h +</path> +<path matrix="1 0 0 1 -0.061 -69.254" stroke="black" arrow="normal/tiny"> +521 292.923 m +600 293.648 l +</path> +<path matrix="1 0 0 1 -0.061 -149.254" stroke="black" arrow="normal/tiny"> +521 292.923 m +600 293.648 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 4 0" stroke="black" arrow="normal/small"> +539.766 93 m +539.306 79.0026 l +340 79.7439 l +</path> +<path matrix="1 0 0 1 4 0" fill="lightblue"> +447.064 116 m +447.064 92 l +632 92 l +632 116 l +h +</path> +<path matrix="1.21414 0.582107 -1.21414 0.582107 363.61 -219.929" fill="lightgray"> +304 384 m +304 320 l +368 320 l +368 384 l +h +</path> +<path matrix="1 0 0 1 4 -3" fill="lightblue"> +225.588 267.631 m +225.588 257.004 l +451.999 257.004 l +451.999 267.631 l +h +</path> +<path matrix="1 0 0 1 -5.33315 0" fill="lightblue"> +286.577 417.212 m +286.577 407.581 l +412.989 407.581 l +412.989 417.212 l +h +</path> +<path matrix="1 0 0 1 4 0" stroke="black"> +-66.4757 363.53 m +-66.4757 358.467 l +-65.4632 358.467 l +-65.4632 363.53 l +h +</path> +<path matrix="8.74693 0 0 0.672878 -2760.71 189.213" fill="lightblue"> +330 430 m +330 390 l +380 390 l +380 430 l +h +</path> +<text matrix="0.781914 0 0 0.829268 129.776 77.4777" transformations="translations" pos="0 474" stroke="black" type="minipage" width="429.348" height="11.4576" depth="0" halign="center" valign="top" size="small" style="center">\begin{tiny} +\tt {\bf phy\_procedures\_eNB\_TX}(sched\_subframe,eNB,abstraction\_flag,r\_type,rn) +\end{tiny} +</text> +<text matrix="1 0 0 1 -143 3" transformations="translations" pos="362.664 511.871" stroke="red" type="label" width="207.355" height="8.3232" depth="2.304" valign="baseline" size="small">\begin{tiny} eNB instance and component carriers \end{tiny}</text> +<text matrix="1 0 0 1 -351.27 2.39657" transformations="translations" pos="362.664 511.871" stroke="red" type="label" width="191.82" height="8.3016" depth="0" valign="baseline" size="small">\begin{tiny} subframe where TX was scheduled \end{tiny}</text> +<path matrix="1 0 0 1 4 0" stroke="red" arrow="normal/small"> +293.168 472.33 m +189.522 511.272 l +</path> +<path matrix="1 0 0 1 4 0" stroke="red" arrow="normal/small"> +372.849 474.127 m +310.542 512.47 l +</path> +<text matrix="1.00926 0 0 0.961538 41.9142 43.5872" transformations="translations" pos="385.43 499.889" stroke="red" type="minipage" width="222.269" height="19.1256" depth="7.176" valign="top" size="small">\setstretch{.5}\begin{tiny} Flag to indicate 212/213 Split\\(transport channels, no 211 procedures) \end{tiny}</text> +<path matrix="1 0 0 1 4 0" stroke="red" arrow="normal/small"> +432.16 473.528 m +526.22 499.29 l +</path> +<path matrix="1.28305 0 0 0.427959 -151.6 291.984" stroke="red"> +27.6629 0 0 27.6629 531.612 404.032 e +</path> +<path matrix="1 0 0 1 4 0" stroke="red" arrow="normal/small"> +526.819 478.92 m +598.712 484.312 l +</path> +<text matrix="1 0 0 1 -6.1848 4.19374" transformations="translations" pos="606.5 493.299" stroke="red" type="minipage" width="138.992" height="11.9544" depth="0" valign="top" size="small">\begin{tiny} Experimental (for relays)\end{tiny}</text> +<text matrix="1 0 0 1 -5.33315 0" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="126.411" height="9.6312" depth="0" halign="center" valign="top" size="small">\begin{tiny} +\bf\tt Check for dead UEs +\end{tiny}</text> +<path matrix="1.21414 0.582107 -1.21414 0.582107 363.876 -64.4895" fill="lightgray"> +304 384 m +304 320 l +368 320 l +368 384 l +h +</path> +<path matrix="1 0 0 1 4 0" stroke="black" arrow="normal/small"> +340.45 451.636 m +340.45 417.212 l +</path> +<text matrix="1 0 0 1 -16 -23" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="11.2364" depth="0" halign="center" valign="top" style="center">\begin{tiny}\tt eNB$\rightarrow$CC\_id==0?\end{tiny}</text> +<text matrix="1 0 0 1 -56.9892 -152.581" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="10.6272" depth="0" halign="center" valign="top" size="small">\begin{tiny} +\bf\tt Call eNB\_dlsch\_ulsch\_scheduler [MAC] +\end{tiny}</text> +<path matrix="1 0 0 1 3.55 -44.424" stroke="black" arrow="normal/small"> +340.45 451.636 m +340.45 417.212 l +</path> +<path matrix="1 0 0 1 3.55 -152.424" stroke="black" arrow="normal/small"> +340.45 451.636 m +340.45 417.212 l +</path> +<path matrix="1 0 0 1 3.55 -197.424" stroke="black" arrow="normal/small"> +340.45 451.636 m +340.45 417.212 l +</path> +<path matrix="1 0 0 1 4 0" stroke="black" arrow="normal/small"> +418.155 336 m +528 336 l +528 248 l +340 247.665 l +</path> +<text matrix="1 0 0 1 4 0" transformations="translations" pos="420 344" stroke="black" type="label" width="12.9096" height="5.3136" depth="0" valign="baseline" size="small">\tiny no</text> +<path matrix="0.573318 0 0 1.1292 147.381 -192.209" fill="lightblue"> +225.588 267.631 m +225.588 257.004 l +451.999 257.004 l +451.999 267.631 l +h +</path> +<text matrix="1 0 0 1 -22 -177.724" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="129.761" height="9.6312" depth="0" halign="center" valign="top" size="small" style="center">\begin{tiny}\tt is PMCH subframe?\end{tiny}</text> +<text matrix="1 0 0 1 -56.9892 -308.305" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="10.9584" depth="0" halign="center" valign="top" size="small" style="center">\begin{tiny} +\bf\tt Call pmch\_procedures +\end{tiny}</text> +<path matrix="1 0 0 1 3.55 -308.424" stroke="black" arrow="normal/small"> +340.45 451.636 m +340.45 417.212 l +</path> +<path matrix="1 0 0 1 4 1" stroke="black" arrow="normal/small"> +340 97.4877 m +340 52 l +</path> +<text matrix="1 0 0 1 4 -155.724" transformations="translations" pos="420 344" stroke="black" type="label" width="12.9096" height="5.3136" depth="0" valign="baseline" size="small">\tiny no</text> +<text matrix="1 0 0 1 164.487 -301.212" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="17.2968" depth="5.352" valign="top" size="small">\setstretch{.5} +\begin{tiny} +\bf\tt Call common\_signal\_procedures\\ +(CS-RS/PSS/SSS/PBCH) +\end{tiny}</text> +<path matrix="1 0 0 1 4 0" stroke="black" arrow="normal/small"> +417.889 180.561 m +540 180 l +539.532 116 l +</path> +<path matrix="1 0 0 1 -24.1093 40" fill="lightgreen"> +352 0 m +352 12 l +384 12 l +384 12 l +384 0 l +368 -12 l +368 -12 l +h +</path> +<text matrix="1 0 0 1 199 0" transformations="translations" pos="176 556" stroke="black" type="label" width="219.988" height="19.3704" depth="0" halign="center" valign="baseline">eNB TX Flowchart</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="0.611694 0 0 2.48525 137.723 -162.718" fill="lightblue"> +225.588 267.631 m +225.588 257.004 l +451.999 257.004 l +451.999 267.631 l +h +</path> +<text matrix="1 0 0 1 -54.8216 84.695" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="17.2968" depth="5.352" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call get\_dci\_sdu [MAC]\\ dci=first\_dci +\end{tiny}</text> +<path matrix="1 0 0 1 -23.3752 0" stroke="black" rarrow="normal/small"> +368.672 502.411 m +368 524 l +</path> +<path matrix="1.21414 0.582107 -1.21414 0.582107 364.387 16.9945" fill="lightgray"> +304 384 m +304 320 l +368 320 l +368 384 l +h +</path> +<text matrix="1 0 0 1 -14.4181 67.484" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt dci not empty and DL dci?\end{tiny}</text> +<path matrix="1 0 0 1 -23.3751 -48.205" stroke="black" rarrow="normal/small"> +368.672 502.411 m +368 524 l +</path> +<path matrix="1 0 0 1 -23 0" stroke="black" rarrow="normal/small"> +368.297 357.206 m +368 380 l +</path> +<path matrix="1 0 0 1 -23 0" fill="lightblue"> +260 356 m +260 328 l +476 328 l +476 356 l +h +</path> +<text matrix="1 0 0 1 -54.7825 -63.7328" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="17.2968" depth="5.352" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call generate\_dlsch\_params\_from\_dci\\ +dci=next(dci) +\end{tiny}</text> +<text matrix="1 0 0 1 -43 0" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<path matrix="1 0 0 1 -23 0" stroke="black" arrow="normal/small"> +260 342 m +240.242 342 l +240 472 l +368 472 l +</path> +<path matrix="1 0 0 1 -23 0" stroke="black" arrow="normal/small"> +445.666 417.484 m +512.662 417.484 l +512.662 303.725 l +367.862 303.725 l +367.862 288.454 l +</path> +<path matrix="1 0 0 1 -23 -68" fill="lightblue"> +260 356 m +260 328 l +476 328 l +476 356 l +h +</path> +<text matrix="1 0 0 1 -54.7825 -131.733" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="16.8048" depth="4.848" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call phy\_config\_dedicated\_step2\\ +dci=first\_dci +\end{tiny}</text> +<path fill="lightgray"> +272 200 m +344.961 161.229 l +416 200 l +344.961 235.739 l +h +</path> +<text matrix="1 0 0 1 -14.4181 -151.516" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt dci not empty and UL dci?\end{tiny}</text> +<path matrix="1 0 0 1 -23 -219" stroke="black" rarrow="normal/small"> +368.297 357.206 m +368 380 l +</path> +<path matrix="1 0 0 1 -23 -219" fill="lightblue"> +260 356 m +260 328 l +476 328 l +476 356 l +h +</path> +<text matrix="1 0 0 1 -54.7825 -282.733" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="17.2968" depth="5.352" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call generate\_ulsch\_params\_from\_dci\\ +dci=next(dci) +\end{tiny}</text> +<text matrix="1 0 0 1 -43 -219" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<path matrix="1 0 0 1 -23 0" stroke="black" arrow="normal/small"> +260 123 m +240.242 123 l +240 252 l +368 252 l +</path> +<path stroke="black" arrow="normal/small"> +416 200 m +488 200 l +489 96 l +345 96 l +344.862 77.0895 l +</path> +<path fill="lightblue"> +272 80 m +272 48 l +416 48 l +416 80 l +h +</path> +<text matrix="1 0 0 1 -54.7825 -343.733" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="18.1416" depth="6.168" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call generate\_dci\_top\\ +Call generate\_phich\_top +\end{tiny}</text> +<path matrix="1 0 0 1 -23.297 -121.206" stroke="black" rarrow="normal/small"> +368.297 357.206 m +368 380 l +</path> +<path matrix="1 0 0 1 -23 12" fill="lightgreen"> +352 0 m +352 12 l +384 12 l +384 12 l +384 0 l +368 -12 l +368 -12 l +h +</path> +<path stroke="black" rarrow="normal/small"> +344 24 m +344 48 l +</path> +<text matrix="1 0 0 1 40 56" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<text matrix="1 0 0 1 41 -164" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<text matrix="1 0 0 1 179 0" transformations="translations" pos="176 556" stroke="black" type="label" width="219.988" height="19.3704" depth="0" halign="center" valign="baseline">eNB TX Flowchart</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 0 15" fill="lightblue"> +240 96 m +240 56 l +496 56 l +496 96 l +h +</path> +<text matrix="1 0 0 1 -47.7825 -306.39" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="258.411" height="23.6472" depth="11.688" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt dlsch\_eNB[UE].subframe\_active=false\par [no PUCCH ACK to be checked in TTI n+k]\par +UE=next(UE) +\end{tiny}</text> +<path matrix="1 0 0 1 0 -161" fill="lightgray"> +288 464 m +368 432 l +448 464 l +368 496 l +h +</path> +<path matrix="1 0 0 1 0 -73" fill="lightgray"> +288 464 m +368 432 l +448 464 l +368 496 l +h +</path> +<path stroke="black" arrow="normal/small"> +368 528 m +368 512 l +</path> +<path matrix="1 0 0 1 0 15" fill="lightgray"> +288 464 m +368 432 l +448 464 l +368 496 l +h +</path> +<text matrix="1 0 0 1 9.5819 128.484" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt is dlsch\_SI active?\end{tiny}</text> +<path matrix="1 0 0 1 0 -81" stroke="black" arrow="normal/small"> +368 528 m +368 504 l +</path> +<text matrix="1 0 0 1 9.5819 26.484" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="center" style="center">\setstretch{.5}\begin{tiny}\tt is dlsch\_P active?\end{tiny}</text> +<path matrix="1 0 0 1 0 -169" stroke="black" arrow="normal/small"> +368 528 m +368 504 l +</path> +<text matrix="1 0 0 1 9.5819 -48.516" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt is dlsch\_RA active?\end{tiny}</text> +<text matrix="1 0 0 1 -57 63" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<text matrix="1 0 0 1 -57 -33" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<text matrix="1 0 0 1 -54 -107" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<path matrix="1 0 0 1 0 -257" stroke="black" arrow="normal/small"> +368 528 m +368 504 l +</path> +<path matrix="1 0 0 1 -16 -17" fill="lightblue"> +456 480 m +456 464 l +648 464 l +648 480 l +h +</path> +<text matrix="1 0 0 1 137.178 43.695" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="11.4576" depth="0" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call pdsch\_procedures(dlsch\_SI) +\end{tiny}</text> +<path matrix="1 0 0 1 0 15" stroke="black" arrow="normal/small"> +448 464 m +536 464 l +536 448 l +</path> +<path matrix="1 0 0 1 0 15" stroke="black" arrow="normal/small"> +536 432 m +536 424 l +368 424 l +</path> +<text matrix="1 0 0 1 64 119" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<path matrix="1 0 0 1 -16 -105" fill="lightblue"> +456 480 m +456 464 l +648 464 l +648 480 l +h +</path> +<text matrix="1 0 0 1 137.178 -44.305" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="11.4576" depth="0" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call pdsch\_procedures(dlsch\_P) +\end{tiny}</text> +<path matrix="1 0 0 1 0 -73" stroke="black" arrow="normal/small"> +448 464 m +536 464 l +536 448 l +</path> +<path matrix="1 0 0 1 0 -73" stroke="black" arrow="normal/small"> +536 432 m +536 424 l +368 424 l +</path> +<text matrix="1 0 0 1 64 31" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<path matrix="1 0 0 1 -16 -193" fill="lightblue"> +456 480 m +456 464 l +648 464 l +648 480 l +h +</path> +<text matrix="1 0 0 1 137.178 -132.305" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="11.4576" depth="0" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call pdsch\_procedures(dlsch\_RA) +\end{tiny}</text> +<path matrix="1 0 0 1 0 -161" stroke="black" arrow="normal/small"> +448 464 m +536 464 l +536 448 l +</path> +<path matrix="1 0 0 1 0 -161" stroke="black" arrow="normal/small"> +536 432 m +536 424 l +368 424 l +</path> +<text matrix="1 0 0 1 64 -57" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<path matrix="1 0 0 1 0 15" fill="lightblue"> +256 232 m +256 208 l +480 208 l +480 232 l +h +</path> +<text matrix="1 0 0 1 -30.822 -172.305" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="17.2968" depth="5.352" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt UE=first\_UE from UE\_list \par [list of UE with t-CRNTI or CRNTI] +\end{tiny}</text> +<path matrix="1 0 0 1 0 -297" fill="lightgray"> +288 464 m +368 432 l +448 464 l +368 496 l +h +</path> +<text matrix="1 0 0 1 9.5819 -185.516" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.6056" depth="5.656" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt is dlsch\_UE active?\end{tiny}</text> +<path matrix="1 0 0 1 0 -305" stroke="black" arrow="normal/small"> +368 528 m +368 504 l +</path> +<path matrix="1 0 0 1 0 -392" stroke="black" arrow="normal/small"> +368 528 m +368 504 l +</path> +<path matrix="1 0 0 1 -16 -327" fill="lightblue"> +456 480 m +456 464 l +648 464 l +648 480 l +h +</path> +<text matrix="1 0 0 1 137.178 -267.305" transformations="translations" pos="286.577 417.212" stroke="black" type="minipage" width="226.411" height="11.4576" depth="0" halign="center" valign="top" size="small" style="center">\setstretch{.5}\begin{tiny} +\bf\tt Call pdsch\_procedures(dlsch\_UE) +\end{tiny}</text> +<text matrix="1 0 0 1 64 -192" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<path matrix="1 0 0 1 0 -297" stroke="black" arrow="normal/small"> +448 464 m +536 464 l +536 448 l +</path> +<path matrix="1 0 0 1 0 -297" stroke="black" arrow="normal/small"> +536 432 m +536 424 l +368 424 l +</path> +<text matrix="1 0 0 1 -54 -243" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<path matrix="1 0 0 1 0 15" stroke="black"> +416 88 m +416 88 l +416 88 l +416 88 l +h +</path> +<path matrix="1 0 0 1 0 8" fill="lightgray"> +320 32 m +368 16 l +416 32 l +368 48 l +h +</path> +<text matrix="1 0 0 1 9.5819 -318.516" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="11.2364" depth="0" halign="center" valign="top" style="center">\setstretch{.5}\begin{tiny}\tt UE=NULL?\end{tiny}</text> +<path stroke="black" arrow="normal/small"> +368 72 m +368 56 l +</path> +<path stroke="black" arrow="normal/small"> +320 40 m +224 40 l +224 168 l +288 168 l +</path> +<text matrix="1 0 0 1 -94 -323" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="8.5512" depth="0" valign="top" size="small" style="center">\tt\tiny no</text> +<path matrix="1 0 0 1 273 15" fill="lightgreen"> +352 0 m +352 12 l +384 12 l +384 12 l +384 0 l +368 -12 l +368 -12 l +h +</path> +<path stroke="black" arrow="normal/small"> +416 40 m +640 40 l +640 24 l +</path> +<text matrix="1 0 0 1 32 -320" transformations="translations" pos="384 376" stroke="black" type="minipage" width="32" height="9.8808" depth="0" valign="top" size="small" style="center">\tt\tiny yes</text> +<path fill="blue"> +512 48 m +512 32 l +544 32 l +544 48 l +h +</path> +<path stroke="red" pen="fat" arrow="normal/small"> +528 80 m +528 48 l +</path> +<text matrix="1 0 0 1 -27 0" transformations="translations" pos="528 112" stroke="red" type="minipage" width="256" height="18.468" depth="6.504" valign="top" size="small">\bf\setstretch{.5}\tiny IF4p5 \par [All Frequency-domain Signals are created]</text> +<text matrix="1 0 0 1 183 0" transformations="translations" pos="176 556" stroke="black" type="label" width="219.988" height="19.3704" depth="0" halign="center" valign="baseline">eNB TX Flowchart</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 0 16" fill="lightgray"> +130 527 m +130 -1 l +608 0 l +608 528 l +h +</path> +<path matrix="1 0 0 1 21 16" fill="gold"> +388 288 m +388 208 l +584 208 l +584 288 l +h +</path> +<path matrix="1 0 0 1 0 16" fill="lightgreen"> +141 449 m +141 361 l +580.427 361 l +580 448 l +h +</path> +<path matrix="1 0 0 1 0 16" stroke="black" fill="white"> +464 428 m +464 396 l +576 396 l +576 428 l +h +</path> +<path matrix="1 0 0 1 -148 100" fill="lightyellow"> +462.358 361 m +462.358 287.368 l +602 287.368 l +602 361 l +h +</path> +<path matrix="1 0 0 1 0 16" fill="lightcyan"> +462.358 361 m +462.358 287.368 l +602 287.368 l +602 361 l +h +</path> +<path matrix="1 0 0 1 0 16" fill="pink"> +492 200 m +492 16 l +596 16 l +596 200 l +h +</path> +<path matrix="1 0 0 1 0 19" fill="lightblue"> +130 202.157 m +130 16 l +484 16 l +484 204 l +h +</path> +<text matrix="1 0 0 1 -168 -251" transformations="translations" pos="300 280" stroke="black" type="minipage" width="397.2" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:phy\_procedures\_eNB\_RX()</text> +<path matrix="1 0 0 1 687 40" fill="gold" tiling="rising"> +0 424 m +0 32 l +48 32 l +48 424 l +h +</path> +<text matrix="1 0 0 1 670 -91" transformations="translations" pos="32 416" stroke="black" type="minipage" width="32" height="50.1172" depth="36.204" valign="top" style="center">M\\ +A\\ +C</text> +<path matrix="1 0 0 1 515 12" stroke="black" arrow="normal/small"> +64 416 m +172 416 l +</path> +<text matrix="1 0 0 1 515 12" transformations="translations" pos="72 440" stroke="black" type="minipage" width="96" height="16.898" depth="2.94" valign="top">\setstretch{.5}\tt\tiny RACH Preamble</text> +<path matrix="1 0 0 1 0 9" stroke="black" arrow="normal/small"> +534 125.858 m +688 126 l +</path> +<text matrix="1 0 0 1 491 -280" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.9404" depth="1.96" valign="top">\tt\tiny ULSCH\_SDU(UE\_id)</text> +<text matrix="1 0 0 1 -523.368 259.368" pos="596 32" stroke="black" type="label" width="156.192" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny eNB\_common\_vars.rxdataF[0]</text> +<text matrix="1 0 0 1 -530.368 235.368" pos="596 32" stroke="black" type="label" width="168.646" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny eNB\_common\_vars.rxdataF[R-1]</text> +<path matrix="2.16129 0 0 1 -478.452 16" stroke="black" arrow="normal/small"> +273 269 m +412 268 l +</path> +<path matrix="2.14286 0 0 1 -469.857 12" stroke="black" arrow="normal/small"> +273 245 m +412 244 l +</path> +<path matrix="1 0 0 1 -53 16" stroke="black" fill="1"> +184 128 m +184 100 l +276 100 l +276 128 l +h +</path> +<text matrix="1 0 0 1 3.0006 -311" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_ulsch(UE\_id)\par36.211</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/tiny"> +208 240 m +208 128 l +</path> +<text matrix="1 0 0 1 147 25" transformations="translations" pos="168 372" stroke="black" type="minipage" width="364" height="11.4576" depth="0" valign="top" size="small">\tt\tiny LTE\_TRANSPORT/prach.c</text> +<text matrix="1 0 0 1 -27 -327" transformations="translations" pos="168 372" stroke="black" type="minipage" width="364" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/PHY/LTE\_TRANSPORT/ulsch\_demodulation.c</text> +<path matrix="1 0 0 1 21 16" stroke="black" fill="white"> +393 285 m +393 229 l +552 228 l +552 284 l +h +</path> +<text matrix="1 0 0 1 287 -161.705" transformations="translations" pos="128 440" stroke="black" type="minipage" width="161" height="10.6272" depth="0" valign="center" size="small">\tt\tiny lte\_eNB\_I0\_measurements()</text> +<group matrix="1 0 0 1 -49 16"> +<group> +<path stroke="black" fill="white"> +280 32 m +280 199 l +308 199 l +308 32 l +h +</path> +<text matrix="0 1 -1 0 734.001 -92" pos="128 440" stroke="black" type="minipage" width="164" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_extract\_rbs\_single()\par36.211</text> +</group> +</group> +<group matrix="1 0 0 1 -65 16"> +<path stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 786.001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="16.6824" depth="4.704" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny lte\_ul\_channel\_estimation()\par36.211</text> +</group> +<group matrix="1 0 0 1 -93 16"> +<path matrix="1 0 0 1 100 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 886.001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_detection\_mrc()\par36.211</text> +</group> +<group matrix="1 0 0 1 -101 16"> +<path matrix="1 0 0 1 144 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 930.001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny frequency\_equalization()\par36.211</text> +</group> +<group matrix="1 0 0 1 -46 16"> +<path matrix="1 0 0 1 125 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 911.001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny lte\_idft()\par36.211</text> +</group> +<group matrix="1 0 0 1 -54 16"> +<path matrix="1 0 0 1 169 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 955.001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_XXX\_llr()\par36.211</text> +</group> +<group matrix="1 0 0 1 -39 16"> +<path matrix="1 0 0 1 213 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 1001 -95" pos="128 440" stroke="black" type="minipage" width="164" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_decoding()\par36.212</text> +</group> +<group matrix="1 0 0 1 -20 16"> +<path matrix="1 0 0 1 -9 0" stroke="black" fill="white"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<group> +<text matrix="0 1 -1 0 777.001 -96" pos="128 440" stroke="black" type="minipage" width="164" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_channel\_compensation()\par36.211</text> +</group> +</group> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/small"> +476 118 m +504.475 118 l +</path> +<path matrix="1 0 0 1 0 16" stroke="black"> +564 220 m +564 220 l +564 220 l +564 220 l +h +</path> +<text matrix="1 0 0 1 326 -327" transformations="translations" pos="168 372" stroke="black" type="minipage" width="112.095" height="10.9584" depth="0" valign="top" size="small">\tt\tiny ulsch\_decoding.c</text> +<path matrix="1 0 0 1 60.209 86" stroke="black" arrow="normal/small"> +476 118 m +504.475 118 l +</path> +<text matrix="1 0 0 1 472.783 -208" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="16.3212" depth="2.352" valign="top">\tt\tiny ACK/NAK,RI,CQI</text> +<path matrix="1 0 0 1 164 16" stroke="black" fill="1"> +131 344 m +131 316 l +276 316 l +276 344 l +h +</path> +<text matrix="1 0 0 1 167.001 -95" transformations="translations" pos="128 440" stroke="black" type="minipage" width="146.013" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny pucch\_procedures(UE\_id)\par36.211</text> +<path matrix="1 0 0 1 324 140" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 349.001 -96" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_pucchl\par36.211</text> +<path matrix="1 0 0 1 77.275 242" stroke="black" arrow="normal/small"> +476 118 m +504.475 118 l +</path> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/small"> +551.76 312.126 m +687 312.231 l +</path> +<text matrix="1 0 0 1 510.907 -68" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="15.9404" depth="1.96" valign="top">\tt\tiny ACK/NAK</text> +<text matrix="1 0 0 1 510.907 -100" transformations="translations" pos="72 440" stroke="black" type="minipage" width="48" height="11.2364" depth="0" valign="top">\tt\tiny SR</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/small"> +440.514 328 m +477 327.572 l +</path> +<text matrix="1 0 0 1 295.239 -57.6321" transformations="translations" pos="168 372" stroke="black" type="minipage" width="112.095" height="11.4576" depth="0" valign="top" size="small">\tt\tiny TRANSPORT/pucch.c</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/tiny"> +373.112 244.28 m +373.112 316 l +</path> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/tiny"> +344.968 268.786 m +345.381 316 l +</path> +<path matrix="1 0 0 1 16 100" stroke="black" fill="1"> +131 344 m +131 316 l +276 316 l +276 344 l +h +</path> +<text matrix="1 0 0 1 43.001 -11" transformations="translations" pos="128 440" stroke="black" type="minipage" width="111.289" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny prach\_procedures\par36.211</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/small"> +405.275 413 m +464 412.625 l +</path> +<path matrix="1 0 0 1 -148 100" stroke="black" arrow="normal/small"> +440.514 328 m +477 327.572 l +</path> +<text matrix="1 0 0 1 -159.361 103" transformations="translations" pos="300 280" stroke="black" type="minipage" width="370.438" height="11.4576" depth="0" valign="top" size="small">\tt\tiny openair1/SCHED/phy\_procedures\_lte\_eNb.c:prach\_procedures()</text> +<path matrix="1 0 0 1 178.191 224" stroke="black" fill="1"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 203.192 -12" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_prachl\par36.211</text> +<text matrix="1 0 0 1 354 -12" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="14.484" depth="2.52" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny E\_PRACH>Lmin\par36.211</text> +<text matrix="1 0 0 1 240.239 -135.632" transformations="translations" pos="168 372" stroke="black" type="minipage" width="250.621" height="10.6272" depth="0" valign="top" size="small">\tt\tiny LTE\_ESTIMATION/lte\_eNB\_I0\_measurements.c</text> +<text matrix="1 0 0 1 203 20" transformations="translations" pos="176 556" stroke="black" type="label" width="299.76" height="19.3704" depth="0" halign="center" valign="baseline">eNB PHY RX Procedures</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/small"> +0 416 m +144 416 l +</path> +<text matrix="1 0 0 1 -592.839 419.285" pos="596 32" stroke="black" type="label" width="207.648" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt eNB->prach\_vars.prachF[0$\cdots$ R-1]}</text> +<path matrix="1 0 0 1 0 16" stroke="black" arrow="normal/tiny"> +160 268 m +160 128 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="0.999446 0 0 2 -0.592063 -512" fill="turquoise"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="0.999446 0 0 0.875 -0.592063 -151" fill="gold"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="0.999446 0 0 1 0.407937 -156" fill="pink"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="0.999446 0 0 1 0.407937 -124" fill="lightyellow"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="0.999446 0 0 1.125 0.407937 -125" fill="lightgreen"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="0.999446 0 0 0.75 0.407937 10" fill="lightgray"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="1 0 0 1 0 -32" fill="lightcyan"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path fill="lightblue"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<path matrix="1 0 0 1 -5 324" stroke="black" fill="1"> +184 128 m +184 100 l +276 100 l +276 128 l +h +</path> +<text matrix="1 0 0 1 51.0006 -3" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_ulsch(UE\_id)\par36.211</text> +<text matrix="1 0 0 1 -69 -7" transformations="translations" pos="68 284" stroke="black" type="label" width="742.558" height="8.9712" depth="8.232" valign="baseline" size="small">\tiny$\mathbf{R}_{r,l}=\mathrm{DFT}_{N_{\mathrm{fft}}}(\mathbf{r}_{r,l}\odot\mathbf{F}_{7.5}),r=0,1,\cdots,R-1,l=0,1,\cdots,N_{\mathrm{symb}}-1$ (\tt\bf eNB\_common\_vars$\rightarrow$rxdataF[][])%,N_{\mathrm{fft}}=2^{1+\left\lceil\log_2 12N^{\mathrm{RB}}_{\mathrm{DL}}\right\rceil$</text> +<path matrix="1 0 0 1 -84 232" stroke="black" fill="lightblue"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 -58.9994 -4" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny slot\_fep\_ul\par36.211</text> +<path stroke="black" arrow="normal/tiny"> +144 440 m +176 440 l +</path> +<path stroke="black" cap="1"> +272 328 m +272 328 l +</path> +<path matrix="1 0 0 1 -108 -4" stroke="black" arrow="normal/tiny"> +144 440 m +176 440 l +</path> +<text transformations="translations" pos="28 468" stroke="black" type="label" width="32.0432" height="6.2048" depth="7.588" valign="baseline">\tiny $\mathbf{r}_{r,l}$</text> +<text matrix="1 0 0 1 128 4" transformations="translations" pos="28 468" stroke="black" type="label" width="38.7464" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{r,l}$</text> +<text matrix="1 0 0 1 276 -132" transformations="translations" pos="28 468" stroke="black" type="label" width="71.1956" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{\mathrm{ext},r,l}$</text> +<text matrix="1 0 0 1 -24 -224" transformations="translations" pos="28 468" stroke="black" type="label" width="693.216" height="8.9712" depth="6.504" valign="baseline" size="small">\tiny $R_{\mathrm{ext},r,l}(n)={R}_{r,l}(12\mathrm{firstPRB}+n),n=0,1,\cdots,12N_{\mathrm{PRB}}-1$ (\tt\bf eNB\_pusch\_vars$\rightarrow$ulsch\_rxdataF\_ext[][])</text> +<text matrix="1 0 0 1 340 -156" transformations="translations" pos="28 468" stroke="black" type="label" width="39.4436" height="13.062" depth="7.588" valign="baseline">\tiny $\mathbf{\hat{H}}_{r,l}$</text> +<text matrix="1 0 0 1 -28 -246" transformations="translations" pos="28 468" stroke="black" type="label" width="631.046" height="11.196" depth="9.12" valign="baseline" size="small">\tiny $\mathbf{\hat{H}}_{r,l} = \mathbf{R}_{\mathrm{ext},r,l}\odot\mathbf{DRS}^*_{l}(\mathrm{cyclicShift},n_{\mathrm{DMRS}^{(2)}},n_{\mathrm{PRS}})$, (\tt\bf eNB\_pusch\_vars$\rightarrow$drs\_ch\_estimates[])</text> +<text matrix="1 0 0 1 392 -128" transformations="translations" pos="28 468" stroke="black" type="label" width="88.9196" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{\mathrm{comp},r,l}$</text> +<text matrix="1 0 0 1 452 -156" transformations="translations" pos="28 468" stroke="black" type="label" width="89.5328" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{\mathrm{comp},0,l}$</text> +<text matrix="1 0 0 1 -28 -320" transformations="translations" pos="28 468" stroke="black" type="label" width="247.932" height="14.2848" depth="6.504" valign="baseline" size="small">\tiny $\mathbf{R}_{\mathrm{comp},0,l}=\frac{1}{R}\sum_{r=0}^{R-1}\mathbf{R}_{\mathrm{comp},r,l}$</text> +<text matrix="1 0 0 1 512 -128" transformations="translations" pos="28 468" stroke="black" type="label" width="89.5328" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{\mathrm{comp},0,l}$</text> +<text matrix="1 0 0 1 572 -156" transformations="translations" pos="28 468" stroke="black" type="label" width="82.8324" height="6.2048" depth="7.588" valign="baseline">\tiny $\mathbf{r}_{\mathrm{comp},0,l}$</text> +<text matrix="1 0 0 1 -28 -345" transformations="translations" pos="28 468" stroke="black" type="label" width="528.362" height="17.3352" depth="12.792" valign="baseline" size="small">\tiny $R_{\mathrm{comp},0,l}(n)=R_{\mathrm{comp},0,l}(n)\dot Q_8\left(\frac{1}{|\hat{H}(n)|^2+I_0}\right), \hat{H}(n)=\sum_{r=0}^{R-1}\hat{H}_{r}(n)$</text> +<text matrix="1 0 0 1 -3 15" transformations="translations" pos="4 192" stroke="black" type="minipage" width="728" height="23.3184" depth="11.376" valign="top" size="small">\tiny $\mathbf{R}_{\mathrm{comp},r,l}=\mathbf{\hat{H}}_r\odot\mathbf{R}_{\mathrm{ext},r,l}2^{-\log_2|H_\mathrm{max}|}, \mathbf{\hat{H}}_r = \frac{1}{2}(\mathbf{\hat{H}}_{r,3}+\mathbf{\hat{H}}_{r,10})$\par (\tt\bf eNB\_pusch\_vars$\rightarrow$ulsch\_rxdataF\_comp)</text> +<text matrix="1 0 0 1 624 -124" transformations="translations" pos="28 468" stroke="black" type="label" width="19.8156" height="9.6964" depth="4.872" valign="baseline">\tiny $\mathbf{\lambda}_{l}$</text> +<text matrix="1 0 0 1 -28 -402" transformations="translations" pos="28 468" stroke="black" type="label" width="636.775" height="8.9712" depth="6.504" valign="baseline" size="small">\tiny QPSK : $\lambda_l(2n)=\mathrm{Re}(r_{\mathrm{comp},0,l}(n)), \lambda_l(2n+1)=\mathrm{Im}(r_{\mathrm{comp},0,l}(n))$ (\tt\bf eNB\_pusch\_vars$\rightarrow$ulsch\_llr)</text> +<text matrix="1 0 0 1 -28 -374" transformations="translations" pos="28 468" stroke="black" type="label" width="287.525" height="8.9616" depth="8.064" valign="baseline" size="small">\tiny ${\mathbf r}_{\mathrm{comp},0,l} = \mathrm{IDFT}_{12N_{\mathrm{PRB}}}({\mathbf R}_{\mathrm{comp},0,l})$</text> +<text matrix="1 0 0 1 0 23" transformations="translations" pos="4 28" stroke="black" type="minipage" width="720" height="24.1008" depth="12.144" valign="top" size="small">\tiny 16QAM : $\lambda_l(4n)=\mathrm{Re}(r_{\mathrm{comp},0,l}(n)), \lambda_l(4n+2)=\mathrm{Im}(r_{\mathrm{comp},0,l}(n))$\par$\lambda_l(4n+1)=|\mathrm{Re}(r_{\mathrm{comp},0,l}(n))|-2\overline{|h(n)|},\lambda_l(4n+3)=|\mathrm{Im}(r_{\mathrm{comp},0,l}(n))|-2\overline{|h(n)|}$</text> +<path matrix="1 0 0 1 -1 324" stroke="black" fill="lightcyan"> +280 32 m +280 199 l +308 199 l +308 32 l +h +</path> +<text matrix="0 1 -1 0 733.001 232" pos="128 440" stroke="black" type="minipage" width="164" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_extract\_rbs\_single()\par36.211</text> +<path matrix="1 0 0 1 5 324" stroke="black" fill="lightgray"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 791.001 229" pos="128 440" stroke="black" type="minipage" width="164" height="16.6824" depth="4.704" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny lte\_ul\_channel\_estimation()\par36.211</text> +<path matrix="1 0 0 1 63 324" stroke="black" fill="lightgreen"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<group matrix="1 0 0 1 72 324"> +<text matrix="0 1 -1 0 777.001 -96" pos="128 440" stroke="black" type="minipage" width="164" height="17.5032" depth="5.544" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_channel\_compensation()\par36.211</text> +</group> +<path matrix="1 0 0 1 121 324" stroke="black" fill="lightyellow"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 907.001 229" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_detection\_mrc()\par36.211</text> +<path matrix="1 0 0 1 179 324" stroke="black" fill="pink"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 965.001 229" pos="128 440" stroke="black" type="minipage" width="164" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny frequency\_equalization()\par36.211</text> +<path matrix="1 0 0 1 237 324" stroke="black" fill="gold"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 1023 229" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny lte\_idft()\par36.211</text> +<path matrix="1 0 0 1 295 324" stroke="black" fill="turquoise"> +332 32 m +332 199 l +360 199 l +360 32 l +h +</path> +<text matrix="0 1 -1 0 1081 229" pos="128 440" stroke="black" type="minipage" width="164" height="15.492" depth="3.504" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny ulsch\_XXX\_llr()\par36.211</text> +<path stroke="black"> +304 236 m +304 236 l +304 236 l +304 236 l +h +</path> +<text matrix="1 0 0 1 199 0" transformations="translations" pos="176 556" stroke="black" type="label" width="320.138" height="19.3704" depth="0" halign="center" valign="baseline">eNB ULSCH Demodulation</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 199 0" transformations="translations" pos="176 556" stroke="black" type="label" width="273.104" height="19.3704" depth="0" halign="center" valign="baseline">eNB PRACH Detection</text> +<path matrix="1 0 0 1 0.643 45" fill="lightblue"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<text matrix="1 0 0 1 -68.357 38" transformations="translations" pos="68 284" stroke="black" type="label" width="505.402" height="8.9616" depth="8.064" valign="baseline" size="small">\tiny$\mathbf{R}_{r}=\mathrm{DFT}_{N_{\mathrm{PRACH}}}(\mathbf{r}_{r}),r=0,1,\cdots,R-1$ (\tt\bf lte\_eNB\_prach\_vars$\rightarrow$rxsigF[])%,N_{\mathrm{fft}}=2^{1+\left\lceil\log_2 12N^{\mathrm{RB}}_{\mathrm{DL}}\right\rceil$</text> +<path matrix="1 0 0 1 -0.879076 13" fill="lightcyan"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<text matrix="1 0 0 1 -69.8791 6" transformations="translations" pos="68 284" stroke="black" type="label" width="501.238" height="10.392" depth="4.776" valign="baseline" size="small">\tiny$\mathbf{R}_{\mathrm{comp},r}=\mathbf{R}_{r}\odot \mathbf{X}^*_u[i],r=0,1,\cdots,R-1$ (\tt\bf lte\_eNB\_prach\_vars$\rightarrow$prachF[])%,N_{\mathrm{fft}}=2^{1+\left\lceil\log_2 12N^{\mathrm{RB}}_{\mathrm{DL}}\right\rceil$</text> +<path matrix="1 0 0 1 -1.80008 -19" fill="lightgray"> +0 296 m +0 264 l +736 264 l +736 296 l +h +</path> +<text matrix="1 0 0 1 -70.8001 -26" transformations="translations" pos="68 284" stroke="black" type="label" width="569.174" height="10.1688" depth="5.904" valign="baseline" size="small">\tiny$\mathbf{r}_{839,r}=\mathrm{IDFT}_{1024}\left(\mathbf{R}_{\mathrm{comp},r}\right), r=0,1,\cdots,R-1$ (\tt\bf lte\_eNB\_prach\_vars$\rightarrow$prach\_ifft[])</text> +<path matrix="1 0 0 1 -61 -2" fill="lightblue"> +112 460 m +112 400 l +176 400 l +176 460 l +h +</path> +<text matrix="1 0 0 1 -25 -8" transformations="translations" pos="28 468" stroke="black" type="label" width="19.922" height="6.216" depth="2.772" valign="baseline">\tiny $\mathbf{r}_{r}$</text> +<path matrix="1 0 0 1 -127.121 -8" stroke="black" arrow="normal/tiny"> +144 440 m +176 440 l +</path> +<text matrix="1 0 0 1 -54 -2" transformations="translations" pos="112 439.386" stroke="black" type="minipage" width="64" height="14.2992" depth="2.304" valign="top" size="small">DFT</text> +<text matrix="1 0 0 1 95 -8" transformations="translations" pos="28 468" stroke="black" type="label" width="26.6224" height="9.5872" depth="2.772" valign="baseline">\tiny $\mathbf{R}_{r}$</text> +<path matrix="1 0 0 1 -61 -66" fill="lightcyan"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 -55 -64" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="13.9488" depth="1.992" valign="top" size="small">$\odot$</text> +<path matrix="1 0 0 1 -61 -1" stroke="black" arrow="normal/tiny"> +176 428 m +208 428 l +208 456 l +268 456 l +</path> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +208 428 m +208 400 l +268 400 l +</path> +<text matrix="1 0 0 1 187 16" transformations="translations" pos="28 468" stroke="black" type="label" width="53.3344" height="12.124" depth="5.572" valign="baseline">\tiny $\mathbf{X}^*_{u}(0)$</text> +<text matrix="1 0 0 1 187 -112" transformations="translations" pos="28 468" stroke="black" type="label" width="53.3344" height="12.124" depth="5.572" valign="baseline">\tiny $\mathbf{X}^*_{u}(1)$</text> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +284 480 m +284 468 l +</path> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +284 372 m +284 384 l +</path> +<path matrix="2.375 0 0 1.25 -361.5 -125" fill="lightgray"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 11 -1" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="19.0224" depth="7.08" valign="top" size="small">\tiny$R\times\mathrm{IDFT}_{1024}$</text> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +300 456 m +336 456 l +</path> +<path matrix="1 0 0 1 -61 -56" stroke="black" arrow="normal/tiny"> +300 456 m +336 456 l +</path> +<path matrix="2.375 0 0 1.25 -361.5 -181" fill="lightgray"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 11 -57" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="19.0224" depth="7.08" valign="top" size="small">\tiny$R\times\mathrm{IDFT}_{1024}$</text> +<group matrix="1 0 0 1 -73 -1"> +<path matrix="1.88154 0 0 1 -53.5314 -8" stroke="black"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<group> +<group> +<text matrix="1 0 0 1 183 -6" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="64" height="14.3376" depth="2.376" valign="top" size="small">\tiny$\sum_{r}|\cdot|^2$</text> +</group> +</group> +</group> +<group matrix="1 0 0 1 -73 -57"> +<path matrix="1.88154 0 0 1 -53.5314 -8" stroke="black"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<group> +<group> +<text matrix="1 0 0 1 183 -6" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="64" height="14.3376" depth="2.376" valign="top" size="small">\tiny$\sum_{r}|\cdot|^2$</text> +</group> +</group> +</group> +<group matrix="1 0 0 1 -61 10"> +<path matrix="2.84167 0 0 1.68966 -230.567 -338.034" stroke="black"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 263 -6" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="25.6392" depth="13.68" valign="top" size="small">\tiny max peak in size $\mathrm{NCS}_2$ window, keep delay</text> +</group> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +412 456 m +440 456 l +</path> +<path matrix="1 0 0 1 -61 0" stroke="black" arrow="normal/tiny"> +412 400 m +440 400 l +</path> +<path matrix="1 0 0 1 -61 -3" stroke="black" arrow="normal/tiny"> +500 460 m +532 460 l +</path> +<path matrix="1 0 0 1 -61 -3" stroke="black" arrow="normal/tiny"> +500 460 m +532 460 l +</path> +<path matrix="1 0 0 1 -61 -59" stroke="black" arrow="normal/tiny"> +500 460 m +532 460 l +</path> +<path matrix="1 0 0 1 -61 1" stroke="black" arrow="normal/tiny"> +624 456 m +672 456 l +</path> +<path matrix="1 0 0 1 -61 -55" stroke="black" arrow="normal/tiny"> +624 456 m +672 456 l +</path> +<path matrix="2.84167 0 0 1.68966 -291.567 -384.034" stroke="black"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 202 -52" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="25.6392" depth="13.68" valign="top" size="small">\tiny max peak in size $\mathrm{NCS}_2$ window, keep delay</text> +<text matrix="1 0 0 1 322 -20" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="21.6528" depth="9.696" valign="top" size="small">\tiny\tt preamble\_energy\_list[]\par preamble\_delay\_list[]</text> +<text matrix="1 0 0 1 311 -104" transformations="translations" pos="28 468" stroke="black" type="label" width="54.7904" height="6.2076" depth="6.888" valign="baseline">\tiny $\mathbf{r}_{839,r}$</text> +<text transformations="translations" pos="16 224" stroke="black" type="minipage" width="700" height="104.215" depth="92.448" valign="top" size="small">\small\begin{itemize} +\item PRACH detection is a quasi-optimal non-coherent receiver for vector observations (multiple antennas) +\item correlation is done in the frequency-domain, number of correlations (in the example above 2) depends on {\em zeroCorrelationConfig} configuration parameter +\item peak-detection (for delay estimation) is performed in each NCS time-window +\end{itemize}</text> +<group> +<path matrix="1 0 0 1 -61 -12" fill="lightcyan"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 -55 -10" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="13.9488" depth="1.992" valign="top" size="small">$\odot$</text> +</group> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" fill="lightgreen"> +340 416 m +340 340 l +564 340 l +564 416 l +h +</path> +<path matrix="6.93939 0 0 1 -1513.76 -18" fill="lightcyan"> +268 480 m +268 452 l +300 452 l +300 480 l +h +</path> +<text matrix="1 0 0 1 145 -13" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="15.5088" depth="3.528" valign="top" size="small">\tiny$\sum_{r,l,i}|\cdot|^2$</text> +<text matrix="1 0 0 1 171 101" transformations="translations" pos="301.598 362.627" stroke="black" type="minipage" width="115.562" height="19.572" depth="5.628" halign="center" valign="top" style="center">\begin{tiny}$\stackbin{<}{>}\sigma^2[\mathrm{dB}]$\end{tiny}</text> +<text matrix="1 0 0 1 199 0" transformations="translations" pos="176 556" stroke="black" type="label" width="288.215" height="19.3704" depth="0" halign="center" valign="baseline">eNB PUCCH1 Detection</text> +<path matrix="1 0 0 1 31 336" stroke="black" fill="1"> +184 128 m +184 100 l +276 100 l +276 128 l +h +</path> +<text matrix="1 0 0 1 87.0006 9" transformations="translations" pos="128 440" stroke="black" type="minipage" width="96" height="16.3128" depth="4.344" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny rx\_pucch()\par36.211</text> +<path matrix="1 0 0 1 -48 244" stroke="black" fill="lightblue"> +153 232 m +153 176 l +228 176 l +228 232 l +h +</path> +<text matrix="1 0 0 1 -22.9994 8" transformations="translations" pos="128 440" stroke="black" type="minipage" width="76" height="15.8184" depth="3.84" valign="center" size="small" style="center">\setstretch{.5}\tt\tiny slot\_fep\_ul\par36.211</text> +<path matrix="1 0 0 1 36 12" stroke="black" arrow="normal/tiny"> +144 440 m +176 440 l +</path> +<path matrix="1 0 0 1 -72 8" stroke="black" arrow="normal/tiny"> +144 440 m +176 440 l +</path> +<text matrix="1 0 0 1 36 12" transformations="translations" pos="28 468" stroke="black" type="label" width="32.0432" height="6.2048" depth="7.588" valign="baseline">\tiny $\mathbf{r}_{r,l}$</text> +<text matrix="1 0 0 1 164 16" transformations="translations" pos="28 468" stroke="black" type="label" width="38.7464" height="9.576" depth="7.588" valign="baseline">\tiny $\mathbf{R}_{r,l}$</text> +<text matrix="1 0 0 1 252 22" transformations="translations" pos="28 468" stroke="black" type="label" width="229.617" height="16.1084" depth="6.748" valign="baseline">\tiny $\mathbf{Z}^*_{l}e^{-j2\pi f/16},-3\leq f\leq 2$</text> +<path stroke="black" arrow="normal/tiny"> +308 448 m +352 448 l +</path> +<text matrix="1 0 0 1 84 -16" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="13.9488" depth="1.992" valign="top" size="small">$\odot$</text> +<path matrix="1 0 0 1 63 2" stroke="black" arrow="normal/tiny"> +308 448 m +352 448 l +</path> +<path matrix="1 0 0 1 -31 0" stroke="black" arrow="normal/tiny"> +392 484 m +392 456 l +</path> +<path stroke="black" arrow="normal/tiny"> +328 448 m +328 400 l +352 400 l +</path> +<text matrix="1 0 0 1 83 -64" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="13.9488" depth="1.992" valign="top" size="small">$\odot$</text> +<path matrix="1 0 0 1 -31 -93" stroke="black" rarrow="normal/tiny"> +392 484 m +392 456 l +</path> +<text matrix="1 0 0 1 321 -116" transformations="translations" pos="28 468" stroke="black" type="label" width="24.486" height="12.138" depth="6.748" valign="baseline">\tiny $\mathbf{Z}^*_{l}$</text> +<path stroke="black"> +288 496 m +288 496 l +288 496 l +288 496 l +h +</path> +<path matrix="1 0 0 1 60 -48" stroke="black" arrow="normal/tiny"> +308 448 m +352 448 l +</path> +<path matrix="0.307692 0 0 1 285.231 0" stroke="black"> +412 408 m +412 392 l +464 392 l +464 408 l +h +</path> +<text transformations="translations" pos="412 408" stroke="black" type="minipage" width="52" height="11.5728" depth="0" valign="top" size="small">\tiny$\mathbf{\hat{H}}$</text> +<text matrix="1 0 0 1 143 -96" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="32" height="13.9488" depth="1.992" valign="top" size="small">$\odot$</text> +<path stroke="black" arrow="normal/tiny"> +420 392 m +420 376 l +</path> +<path stroke="black" arrow="normal/tiny"> +384 400 m +384 368 l +412 368 l +</path> +<path stroke="black" arrow="normal/tiny"> +428 368 m +464 368 l +</path> +<text matrix="1 0 0 1 201 -93" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="11.9544" depth="0" valign="top" size="small">\tiny$\mathrm{sgn}(\mathrm{Re}(\cdot))$</text> +<path stroke="black" arrow="normal/tiny"> +444 368 m +444 352 l +464 352 l +</path> +<text matrix="1 0 0 1 201 -109" transformations="translations" pos="268 471.863" stroke="black" type="minipage" width="92" height="11.9544" depth="0" valign="top" size="small">\tiny$\mathrm{sgn}(\mathrm{Im}(\cdot))$</text> +<path stroke="black"> +532 408 m +532 408 l +532 408 l +532 408 l +h +</path> +<text matrix="1 0 0 1 0 -6" transformations="translations" pos="432 472" stroke="black" type="label" width="165.809" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny PUCCH1 (Scheduling Request)</text> +<text matrix="1 0 0 1 0 -54" transformations="translations" pos="432 472" stroke="black" type="label" width="145.519" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny PUCCH1a/1b (ACK/NAK)</text> +<text matrix="1 0 0 1 24 92" transformations="translations" pos="16 224" stroke="black" type="minipage" width="700" height="93.756" depth="81.984" valign="top" size="small">\small\begin{itemize} +\item PUCCH1 detection is a quasi-optimal non-coherent receiver (energy detector) for vector observations (multiple antennas) for scheduling request. Care is taken to handle residual frequency-offset. +\item PUCCH1A/1B detection is quasi-coherent based on a rough channel estimate obtained on the 3 symbols without data modulation. \item In both cases, correlation is done in the frequency-domain +\end{itemize}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 -512 62" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="265.102" depth="253.752" valign="top" size="small">\small\begin{itemize} +\item Threads (all in {\tt targets/RT/USER/lte-ru.c}) +\begin{itemize} +\item {\tt ru\_thread}: Thread per RU which sequentially +performs +\begin{itemize} +\item read from south interface (RF or IF fronthaul) +\item RX processing for subframe $n$ (if necessary). +\item wakeup eNBs that are waiting for signal (if necessary) +\item wait for eNB task completion (if necessary) +\item do TX processing for subframe $n+4$ (if necessary). Note that this can spawn multiple worker threads for very high order spatial processing (e.g. massive-MIMO or DAS for UDN) +\item do outgoing fronthaul (RF or IF fronthaul) +\end{itemize} +\item {\tt ru\_thread\_prach}: Thread for PRACH processing in remote RU (DFT on RX, IF4p5 RRU) +\item {\tt ru\_thread\_asynch}: Thread for asynchronous reception from fronthaul interface (TX direction in RRU). %Allows for some jitter so as not to block the RRU real-time processing. +\end{itemize} +\item Synchronization on fronthaul interface +\begin{itemize} +\item {\em synch\_to\_ext\_device} : synchronizes to incoming samples from RF or Fronthaul interface using blocking read +\item {\em synch\_to\_other} : synchronizes via POSIX mechanism to other source (other CC, timer) which maintains real-time. +\end{itemize} +\end{itemize} </text> +<text matrix="1 0 0 1 201 -17" transformations="translations" pos="176 556" stroke="black" type="label" width="140.33" height="19.3704" depth="0" halign="center" valign="baseline">RU Threads</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 -512 78" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="166.006" depth="154.392" valign="top" size="small">\small\begin{itemize} +\item Threads (all in {\tt targets/RT/USER/lte-enb.c}) +\begin{itemize} +\item multi RX/TX thread mode (optional) +\begin{itemize} +\item {\tt eNB\_thread\_rxtx}: 2 threads per CC/Instance which do both RX procedures for subframe $n$ and TX procedures for subframe $n+4$. One operates on even subframes, one on odd. This allows 1ms subframe processing to use multiple-cores. +\end{itemize} +\item common RU-eNB RX/TX thread (default if single RU/eNB) +\begin{itemize} +\item calls {\tt eNB\_top}: procedure per CC/Instance which sequentially +\begin{itemize} +\item blocks on signal from RU +\item RX/TX processing for subframe $n$ and $n+4$ +\item signals completion to RU +\end{itemize} +\end{itemize} +\item {\tt eNB\_prach}: Thread per CC\_id/Instance for PRACH processing +\end{itemize} +\end{itemize} </text> +<text matrix="1 0 0 1 201 -1" transformations="translations" pos="176 556" stroke="black" type="label" width="153.891" height="19.3704" depth="0" halign="center" valign="baseline">eNB Threads</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 64 0" stroke="white" fill="lightblue"> +400 400 m +400 388 l +520 388 l +520 400 l +h +</path> +<path matrix="1 0 0 1 64 0" fill="lightgreen"> +400 432 m +400 420 l +520 420 l +520 432 l +h +</path> +<path matrix="0.46875 0 0 1 336.5 0" fill="pink"> +400 448 m +400 436 l +528 436 l +528 448 l +h +</path> +<path matrix="0.46875 0 0 1 276.5 0" fill="lightyellow"> +400 448 m +400 436 l +528 436 l +528 448 l +h +</path> +<path matrix="0.7 0 0 0.5 -7.4 198" fill="lightblue"> +192 388 m +192 364 l +272 364 l +272 388 l +h +</path> +<path matrix="0.15 0 0 1 107.2 -28" stroke="black" fill="lightgreen"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 183 0" transformations="translations" pos="176 556" stroke="black" type="label" width="390.382" height="20.9244" depth="6.972" halign="center" valign="baseline">eNB Timing (multi-thread mode)</text> +<path matrix="1 0 0 1 80 0" stroke="black"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 80 0" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="11.124" depth="0" valign="top" size="small">\tiny SF $n+1$</text> +<path matrix="1 0 0 1 160 0" stroke="black"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 160 0" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="11.124" depth="0" valign="top" size="small">\tiny SF $n+2$</text> +<path matrix="1 0 0 1 240 0" stroke="black"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 240 0" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="11.124" depth="0" valign="top" size="small">\tiny SF $n+3$</text> +<text matrix="0.15 0 0 0.5 107.2 207" transformations="translations" pos="32 480" stroke="black" type="minipage" width="12" height="8.5512" depth="0" valign="top" size="small">\tiny $n$</text> +<path matrix="0.493671 0 0 1 167.203 -28" stroke="black" fill="pink"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 151 -30" transformations="translations" pos="32 480" stroke="black" type="minipage" width="40" height="10.9584" depth="0" valign="top" size="small">\tiny$n+4$</text> +<path matrix="1 0 0 1 320 0" stroke="black"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 320 0" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="11.124" depth="0" valign="top" size="small">\tiny SF $n+4$</text> +<path stroke="red" arrow="normal/tiny"> +32 480 m +212 572 +352 480 c +</path> +<path stroke="black" cap="1"> +384 464 m +384 464 l +</path> +<path stroke="black" cap="1"> +380 472 m +380 472 l +</path> +<text matrix="1 0 0 1 -16 0" transformations="translations" pos="32 364" stroke="black" type="minipage" width="704" height="72.0944" depth="58.24" valign="top">\tiny\begin{itemize} +\item The current processing requires approximately 1ms peak in each direction (basically 1 core RX, 1core TX). The current architecture will work on a single core if the sum of RX and TX procedures is limited to 1ms. It can fit on 2 cores if the sum of RX,TX and PRACH is less than 2ms. +\item three threads, RX-TX even, RX-TX odd and PRACH. RX-TX blocks until woken by the RU thread with a new RX subframe $n$ that is linked to this eNB process. The RX-TX thread performs ue-specific processing for subframe $n$ and then TX common and ue-specific processing for subframe $n+4$ (frequency-domain generation only). This insures the data dependency between TX $n+4$ and RX $n$ is respected. The duration of this thread should be less than 2ms which can compensate some jitter on the RX processing. +\end{itemize}</text> +<path stroke="black"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny SF $n$</text> +<text transformations="translations" pos="328 512" stroke="red" type="label" width="270.986" height="8.9784" depth="2.976" valign="baseline" size="small">\tiny LTE HARQ periodicity (FDD, TDD can be longer)</text> +<text matrix="1 0 0 1 96 -88" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny PRACH $n$</text> +<path matrix="0.7 0 0 1 103.6 -28" stroke="black" fill="lightyellow"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<path matrix="0.15 0 0 1 187.2 -64" stroke="black" fill="lightgreen"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="0.15 0 0 0.5 191.2 153" transformations="translations" pos="32 480" stroke="black" type="minipage" width="68" height="10.9584" depth="0" valign="top" size="small">\tiny $n+1$</text> +<text matrix="0.15 0 0 0.5 121.2 207" transformations="translations" pos="32 480" stroke="black" type="minipage" width="12" height="8.5512" depth="0" valign="top" size="small">\tiny $n$</text> +<path matrix="0.493671 0 0 1 249.203 -64" stroke="black" fill="pink"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 233 -66" transformations="translations" pos="32 480" stroke="black" type="minipage" width="40" height="10.9584" depth="0" valign="top" size="small">\tiny$n+5$</text> +<path matrix="0.7 0 0 1 185.6 -64" stroke="black" fill="lightyellow"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="0.15 0 0 0.5 203.2 173" transformations="translations" pos="32 480" stroke="black" type="minipage" width="32" height="10.9584" depth="0" valign="top" size="small">\tiny $n+1$</text> +<path stroke="black" arrow="normal/tiny"> +124 424 m +172 416 +152 392 c +</path> +<path stroke="black" arrow="normal/tiny"> +204 424 m +228 424 +236 416 c +</path> +<path matrix="1 0 0 1 0 -12" stroke="black" arrow="normal/tiny"> +192 396 m +196 416 l +</path> +<path matrix="0.15 0 0 1 27.2 -64" stroke="black" fill="lightgreen"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="0.15 0 0 0.5 31.2 153" transformations="translations" pos="32 480" stroke="black" type="minipage" width="68" height="10.9584" depth="0" valign="top" size="small">\tiny $n-1$</text> +<path matrix="0.493671 0 0 1 89.203 -64" stroke="black" fill="pink"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 73 -66" transformations="translations" pos="32 480" stroke="black" type="minipage" width="40" height="10.9584" depth="0" valign="top" size="small">\tiny$n+3$</text> +<path matrix="0.7 0 0 1 25.6 -64" stroke="black" fill="lightyellow"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="0.15 0 0 0.5 43.2 173" transformations="translations" pos="32 480" stroke="black" type="minipage" width="32" height="10.9584" depth="0" valign="top" size="small">\tiny $n-1$</text> +<path matrix="0.7 0 0 1 267.6 -28" stroke="black" fill="lightyellow"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="0.15 0 0 0.5 285.2 209" transformations="translations" pos="32 480" stroke="black" type="minipage" width="56" height="10.9584" depth="0" valign="top" size="small">\tiny $n+2$</text> +<path matrix="0.493671 0 0 1 329.203 -28" stroke="black" fill="pink"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<text matrix="1 0 0 1 313 -30" transformations="translations" pos="32 480" stroke="black" type="minipage" width="40" height="10.9584" depth="0" valign="top" size="small">\tiny$n+6$</text> +<path matrix="0.15 0 0 1 271.2 -28" stroke="black" fill="lightgreen"> +32 480 m +32 464 l +112 464 l +112 480 l +h +</path> +<path stroke="black" arrow="normal/tiny"> +284 424 m +308 424 +316 436 c +</path> +<text matrix="0.15 0 0 0.5 229.2 221" transformations="translations" pos="32 480" stroke="black" type="minipage" width="68" height="10.9584" depth="0" valign="top" size="small">\tiny $n+2$</text> +<path matrix="1 0 0 1 7 6" stroke="black" arrow="normal/tiny"> +268 452 m +276 436 l +</path> +<text matrix="1 0 0 1 63 0" transformations="translations" pos="400 432" stroke="black" type="minipage" width="144" height="10.128" depth="0" valign="top" size="small">\tiny RU thread</text> +<text matrix="1 0 0 1 63 16" transformations="translations" pos="400 432" stroke="black" type="minipage" width="144" height="11.9544" depth="0" valign="top" size="small">\tiny RX-TX thread (even)</text> +<path matrix="0.46875 0 0 1 336.5 -32" fill="pink"> +400 448 m +400 436 l +528 436 l +528 448 l +h +</path> +<path matrix="0.46875 0 0 1 276.5 -32" fill="lightyellow"> +400 448 m +400 436 l +528 436 l +528 448 l +h +</path> +<text matrix="1 0 0 1 63 -16" transformations="translations" pos="400 432" stroke="black" type="minipage" width="144" height="11.9544" depth="0" valign="top" size="small">\tiny RX-TX thread (odd)</text> +<text matrix="1 0 0 1 432 -80" transformations="translations" pos="32 480" stroke="black" type="minipage" width="80" height="10.128" depth="0" valign="top" size="small">\tiny PRACH</text> +<path matrix="1 0 0 1 -160 -12" stroke="black" arrow="normal/tiny"> +192 396 m +196 416 l +</path> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 111 -311" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="1 0 0 1 95 -303" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="1 0 0 1 87 -295" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="1 0 0 1 86 68" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="0.232141 0 0 0.927995 612.286 93.6201" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<path matrix="0.573927 0 0 0.908562 397.291 100.149" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<path matrix="1 0 0 0.673921 67.8375 132.347" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="1 0 0 1 161 7" transformations="translations" pos="176 556" stroke="black" type="label" width="412" height="20.9244" depth="6.972" halign="center" valign="baseline">OAI IF1'' Interface (can be NFAPI)</text> +<text matrix="1 0 0 1 -512 63" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="37.2932" depth="23.38" valign="top">\tiny\begin{itemize} +\item OAI IF1'' is the interface between the 36.321 Medium-Access (MAC) Layer Procedures and the 36.213 Physical Layer Procedures. It links several PHY instances to one MAC instance. +\item It is a configurable (dynamically loadable) module which can implement an (N)FAPI P5/P7 or a simpler interface. +\end{itemize} </text> +<path matrix="0.441741 0 0 0.919575 158.74 96.2351" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 -372.87 383.775" pos="596 32" stroke="black" type="label" width="83.256" height="8.3016" depth="0" valign="baseline" size="small">\tiny Random-Access</text> +<text matrix="1 0 0 1 54.4342 383.743" pos="596 32" stroke="black" type="label" width="35.1312" height="8.3016" depth="0" valign="baseline" size="small">\tiny Events</text> +<text matrix="1 0 0 1 -216.173 19.612" pos="596 32" stroke="black" type="label" width="150.346" height="14.952" depth="4.176" valign="baseline" size="small">\small PHY procedures</text> +<text matrix="0 1 -1 0 266.848 -324.389" pos="596 32" stroke="black" type="label" width="110.765" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt initiate\_ra\_proc()}</text> +<text matrix="0 1 -1 0 290.621 -330.742" pos="596 32" stroke="black" type="label" width="117.118" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt terminate\_ra\_proc()}</text> +<text matrix="0 1 -1 0 314.394 -311.688" pos="596 32" stroke="black" type="label" width="98.064" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt cancel\_ra\_proc()}</text> +<text matrix="0 1 -1 0 367.94 -349.796" pos="596 32" stroke="black" type="label" width="136.171" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_dedicated()}</text> +<text matrix="0 1 -1 0 412.713 -318.039" pos="596 32" stroke="black" type="label" width="104.414" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_sib1()}</text> +<text matrix="0 1 -1 0 436.486 -318.039" pos="596 32" stroke="black" type="label" width="104.414" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_sib2()}</text> +<text matrix="0 1 -1 0 460.259 -324.389" pos="596 32" stroke="black" type="label" width="110.765" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_sib13()}</text> +<path matrix="1 0 0 0.673921 91.6108 132.064" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 115.384 132.064" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 168.93 132.064" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 213.703 132.064" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 237.476 132.064" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 261.249 132.064" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.673921 302.346 132.064" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 501.848 -379.774" pos="596 32" stroke="black" type="label" width="166.15" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt eNB\_dlsch\_ulsch\_scheduler()}</text> +<text matrix="0 1 -1 0 524.637 -298.985" pos="596 32" stroke="black" type="label" width="85.3608" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt get\_dcii\_sdu()}</text> +<path matrix="1 0 0 0.673921 325.134 132.678" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 548.251 -305.336" pos="596 32" stroke="black" type="label" width="91.7112" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt get\_dlsch\_sdu()}</text> +<path matrix="1 0 0 0.673921 347.923 132.69" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 570.214 -262.656" pos="596 32" stroke="black" type="label" width="49.032" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt rx\_sdu()}</text> +<path matrix="1 0 0 0.673921 370.711 132.757" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 593.002 -292.635" pos="596 32" stroke="black" type="label" width="79.0104" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt get\_mch\_sdu()}</text> +<path matrix="1 0 0 0.673921 393.5 132.624" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="0 1 -1 0 701.156 -307.114" pos="596 32" stroke="black" type="label" width="93.4896" height="8.3136" depth="0.984" valign="baseline" size="small">\tiny {\tt SR\_indication()}</text> +<path matrix="1 0 0 0.673921 501.654 133.147" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="0.494718 0 0 0.92251 268.305 95.0367" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 -248.565 384.751" pos="596 32" stroke="black" type="label" width="63.9696" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny PHY Config</text> +<text matrix="1 0 0 1 -92.464 384.743" pos="596 32" stroke="black" type="label" width="56.9952" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny Scheduling</text> +<text matrix="1 0 0 1 0 -16" transformations="translations" pos="0 416" stroke="black" type="minipage" width="224" height="28.9872" depth="17.04" valign="top" size="small">\small {\tt 36.213/36.321}\\ +{\tt openair2/LAYER2/MAC}</text> +<text matrix="1 0 0 1 23 -384" transformations="translations" pos="0 448" stroke="black" type="minipage" width="152" height="28.9872" depth="17.04" valign="top" size="small">\small {\tt 36.211/212}\par +{\tt openair1/PHY}</text> +<path matrix="1 0 0 1 87 -167" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<text matrix="1 0 0 1 -216.173 147.612" pos="596 32" stroke="black" type="label" width="178.164" height="14.9448" depth="0" valign="baseline" size="small">\small OAI MAC interface</text> +<text matrix="0 1 -1 0 391.713 -312.039" pos="596 32" stroke="black" type="label" width="98.064" height="8.3184" depth="2.64" valign="baseline" size="small">\tiny {\tt phy\_config\_mib()}</text> +<path matrix="1 0 0 0.673921 192.703 132.064" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.250151 84.8376 58.5896" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.250151 221.838 58.5896" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.250151 756.838 -125.41" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="1 0 0 0.250151 348.838 58.5896" stroke="black" fill="lightgray" arrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<text matrix="1 0 0 1 -333.87 87.775" pos="596 32" stroke="black" type="label" width="125.146" height="14.9448" depth="0" valign="baseline" size="small">\small UL-Indication</text> +<text matrix="1 0 0 1 -194.87 87.775" pos="596 32" stroke="black" type="label" width="102.482" height="14.952" depth="4.176" valign="baseline" size="small">\small Config-Req</text> +<text matrix="1 0 0 1 -69.87 87.775" pos="596 32" stroke="black" type="label" width="132.761" height="14.952" depth="4.176" valign="baseline" size="small">\small Schedule-Resp</text> +<text matrix="1 0 0 1 -53 0" transformations="translations" pos="104 232" stroke="black" type="minipage" width="216" height="11.816" depth="0" valign="top">\tiny Northbound interface</text> +<text matrix="1 0 0 1 -53 -80" transformations="translations" pos="104 232" stroke="black" type="minipage" width="216" height="11.816" depth="0" valign="top">\tiny Southbound interface</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 161 7" transformations="translations" pos="176 556" stroke="black" type="label" width="217.12" height="19.3704" depth="0" halign="center" valign="baseline">OAI IF1'' Interface</text> +<text matrix="1 0 0 2.62963 -511 -694.148" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="229.141" depth="215.712" valign="top">\tiny\begin{itemize} +\item The PHY end uses three basic messages +\begin{itemize} +\item {\tt CONFIG\_REQ}: this provides the cell configuration and UE-specific configuration to the PHY instances. This comprises the following FAPI P5/P7 messages +\begin{enumerate} +\item CONFIG.request +\item UE\_CONFIG.request (**not used in OAI PHY) +\end{enumerate} +\item {\tt UL\_INDICATION} This is an uplink indication that sends all UL information received in one TTI, including PRACH, if available. It also provides the subframe indication for the DL scheduler. It maps to the following FAPI P7 messages +\begin{enumerate} +\item {\tt SUBFRAME.indication} +\item {\tt HARQ.indication} +\item {\tt CRC.indication } +\item {\tt RX\_ULSCH.indication} +\item {\tt RX\_SR.indication} +\item {\tt RX\_CQI.indication} +\item {\tt RACH.indication} +\item {\tt SRS.indication} +\end{enumerate} +\item {\tt SCHEDULE\_REQUEST} This message contains the scheduling response information and comprises the following FAPI P7 messages +\begin{enumerate} +\item {\tt DL\_CONFIG.request} +\item {\tt UL\_CONFIG.request} +\item {\tt TX.request} +\item {\tt HI\_DCI0.request} +\end{enumerate} +\end{itemize} +\item The module is registered both by PHY and MAC and can implement different types of transport (NFAPI, function call, FAPI over UDP, etc.). During registration, fuction pointers for the different messages are provided for the module to interact with either PHY or MAC or both if they are executing in the same machine. Note that for a networked implementation (e.g. NFAPI), there are north and south components running in different machines. +\end{itemize} </text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 161 7" transformations="translations" pos="176 556" stroke="black" type="label" width="217.12" height="19.3704" depth="0" halign="center" valign="baseline">OAI IF1'' Interface</text> +<text matrix="1 0 0 2.62963 -511 -694.148" transformations="translations" pos="512 464" stroke="black" type="minipage" width="732" height="261.064" depth="247.716" valign="top">\small\begin{itemize} +\item The PHY-layer timing is assumed to be +\begin{enumerate} +\item wait for subframe indication $n$ from HW +\item trigger PRACH if $n$ has PRACH (parallel thread) +\item trigger UE specific RX procedures for $n$ if $n$ is UL +\item assemble {\tt UL\_INDICATION} and send to MAC +\item wait for {\tt SCHEDULE\_REQUEST} +\item do TX procedures if $n+4$ is TX and RX programming if $n+4+k$ is UL +\end{enumerate} +\item The MAC-layer timing is assumed to be +\begin{enumerate} +\item do all UL processing for subframe $n$ if $n$ is UL after unraveling of UL\_INDICATION in MAC module +\item wait for call to {\tt eNB\_dlsch\_ulsch\_scheduler} +\item do DL scheduling for $n+4$ if it is DL +\item do UL scheduling for $n+8$ if it is UL +\item return from eNB\_dlsch\_ulsch\_scheduler +\item let MAC module form SCHEDULE\_REQUEST +\end{enumerate} +\end{itemize} </text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1 0 0 1 86 -220" stroke="black" fill="lightgray"> +96 384 m +96 320 l +640 320 l +640 384 l +h +</path> +<path matrix="0.232141 0 0 0.927995 612.286 -194.38" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<path matrix="0.573927 0 0 0.908562 397.291 -187.851" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 161 7" transformations="translations" pos="176 556" stroke="black" type="label" width="115.455" height="19.3704" depth="0" halign="center" valign="baseline">OAI MAC</text> +<path matrix="0.441741 0 0 0.919575 158.74 -191.765" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 -372.87 95.775" pos="596 32" stroke="black" type="label" width="83.256" height="8.3016" depth="0" valign="baseline" size="small">\tiny Random-Access</text> +<text matrix="1 0 0 1 54.4342 95.743" pos="596 32" stroke="black" type="label" width="35.1312" height="8.3016" depth="0" valign="baseline" size="small">\tiny Events</text> +<path matrix="0.494718 0 0 0.92251 268.305 -192.963" stroke="black" fill="1"> +128 368 m +128 336 l +352 336 l +352 368 l +h +</path> +<text matrix="1 0 0 1 -248.565 96.751" pos="596 32" stroke="black" type="label" width="63.9696" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny PHY Config</text> +<text matrix="1 0 0 1 -92.464 96.743" pos="596 32" stroke="black" type="label" width="56.9952" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny Scheduling</text> +<text matrix="1 0 0 1 16 -368" transformations="translations" pos="0 416" stroke="black" type="minipage" width="224" height="28.0824" depth="16.152" valign="top" size="small">\small {\tt 36.321}\\ +{\tt openair2/LAYER2/MAC}</text> +<path matrix="1 0 0 0.250151 756.838 -125.41" stroke="black" fill="lightgray" rarrow="normal/small"> +175.695 380 m +176.42 128 l +</path> +<path matrix="0.5 0 0 1 241 0" stroke="black"> +176 496 m +176 384 l +400 384 l +400 496 l +h +</path> +<path matrix="1 0 0 1 320 0" stroke="black"> +176 496 m +176 384 l +400 384 l +400 496 l +h +</path> +<text matrix="1 0 0 1 -228.87 399.775" pos="596 32" stroke="black" type="label" width="42.7896" height="14.9448" depth="0" valign="baseline" size="small">\small RRC</text> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +384 384 m +272 144 l +</path> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +384 384 m +384 144 l +</path> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +384 384 m +528 144 l +</path> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +608 384 m +528 144 l +</path> +<text matrix="1 0 0 1 -4.87 399.775" pos="596 32" stroke="black" type="label" width="40.5144" height="14.9448" depth="0" valign="baseline" size="small">\small RLC</text> +<path matrix="1 0 0 1 -128 -128" stroke="black"> +176 496 m +176 384 l +400 384 l +400 496 l +h +</path> +<text matrix="1 0 0 1 -495.87 271.775" pos="596 32" stroke="black" type="label" width="116.184" height="14.952" depth="4.176" valign="baseline" size="small">\small Preprocessor</text> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +160 256 m +528 144 l +</path> +<path stroke="black" arrow="normal/normal" rarrow="normal/normal"> +272 312 m +608 384 l +</path> +<path stroke="black" pen="heavier"> +472 504 m +472 232 l +152 232 l +152 40 l +728 40 l +736 40 l +736 504 l +h +</path> +<text matrix="1 0 0 1 504 72" transformations="translations" pos="0 416" stroke="black" type="minipage" width="224" height="28.0824" depth="16.152" valign="top" size="small">\small {\tt 36.322}\\ +{\tt openair2/LAYER2/RLC}</text> +<text matrix="1 0 0 1 32 0" transformations="translations" pos="0 416" stroke="black" type="minipage" width="224" height="28.0824" depth="16.152" valign="top" size="small">\small {\tt user customizable scheduling module}</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 199 -16" transformations="translations" pos="176 556" stroke="black" type="label" width="163.19" height="19.3928" depth="5.404" halign="center" valign="baseline">TX Precoding</text> +<text matrix="1 0 0 1 0 12" transformations="translations" pos="16 512" stroke="black" type="minipage" width="704" height="162.125" depth="150.504" valign="top" size="small">\small\begin{itemize} +\item Spatio-temporal filtering for muli-cell (vCell) and multi-user transmission. Input and output are frequency-domain signals. +\item can be applied to Rel-10/11/12/13 physical channels and Rel-8 common channels +\begin{itemize} +\item UE-specific precoding (TM7-10) +\item vCell-specific precoding (PDCCH + TM1-6) for groups of UEs +\item PMCH vCells +\end{itemize} +\item Precoding applicable to +\begin{enumerate} +\item indoor DAS +\item outdoor co-localized arrays (e,g, Massive-MIMO) +\item outdoor CoMP +\end{enumerate} +\end{itemize}</text> +<path matrix="0.470395 0 0 0.4 159.158 0" stroke="black" fill="lightgray"> +208 480 m +208 80 l +512 80 l +512 480 l +h +</path> +<path matrix="1 0 0 1 49 -275" stroke="pink" pen="fat" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 49 -323" stroke="darkgray" pen="fat" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 49 -387" stroke="gold" pen="fat" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 0 -37" stroke="lightcyan" fill="gold"> +400 160 +480 192 +528 160 +400 160 +400 160 u +</path> +<path matrix="0.866025 -0.5 0.5 0.866025 9.3796 241.005" stroke="lightyellow" fill="darkgray"> +400 96 +448 128 +512 144 +576 96 +496 80 +400 96 +400 96 u +</path> +<path stroke="black"> +480 160 m +480 160 l +</path> +<path stroke="black"> +496 160 m +496 160 l +</path> +<path matrix="0.866025 0.5 -0.5 0.866025 102.38 -159.995" stroke="lightyellow" fill="pink"> +400 96 +448 128 +512 144 +576 96 +496 80 +400 96 +400 96 u +</path> +<text transformations="translations" pos="512 144" stroke="black" type="label" width="28.4928" height="14.9448" depth="0" valign="baseline" size="small">\small UE</text> +<text matrix="1 0 0 1 16 64" transformations="translations" pos="512 144" stroke="black" type="label" width="44.7144" height="14.9448" depth="0" valign="baseline" size="small">\small vCell</text> +<text matrix="1 0 0 1 32 -96" transformations="translations" pos="512 144" stroke="black" type="label" width="44.7144" height="14.9448" depth="0" valign="baseline" size="small">\small vCell</text> +<text matrix="1 0 0 1 0 -22" transformations="translations" pos="256 144" stroke="black" type="minipage" width="144" height="16.6224" depth="4.632" valign="top" size="small">TX Precoding</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<path layer="alpha" matrix="1.18986 0 0 0.837002 -253.249 49.0308" stroke="0" fill="lightyellow"> +608 516 m +607 37 l +679 37 l +680 516 l +h +</path> +<path matrix="1 0 0 1 -133 -21" stroke="black" fill="white"> +632 360 m +632 188 l +660 188 l +660 360 l +h +</path> +<text matrix="1 0 0 1 199 -16" transformations="translations" pos="176 556" stroke="black" type="label" width="341.835" height="20.9244" depth="6.972" halign="center" valign="baseline">TX Precoding (to RF device)</text> +<path matrix="1 0 0 1 -63 0" stroke="black" fill="lightgray"> +208 480 m +208 80 l +512 80 l +512 480 l +h +</path> +<path matrix="1 0 0 1 -63 -35" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 -63 -99" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 -63 -291" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<text matrix="1 0 0 1 -63 -15" transformations="translations" pos="96 464" stroke="black" type="minipage" width="81.789" height="15.2856" depth="3.312" valign="top" size="small">\tt eNB[0]</text> +<text matrix="1 0 0 1 -63 -79" transformations="translations" pos="96 464" stroke="black" type="minipage" width="81.789" height="15.2856" depth="3.312" valign="top" size="small">\tt eNB[1]</text> +<text matrix="1 0 0 1 -89.2484 -270.814" transformations="translations" pos="96 464" stroke="black" type="minipage" width="129.789" height="21.324" depth="9.36" valign="top" size="small">\tt eNB[CC\_max]</text> +<path matrix="1 0 0 1 424.037 -0.368" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 424.714 -64.365" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 424.714 -320.365" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 424.815 -16.205" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 424.816 -16.2378" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 424.816 -80.2378" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 423.542 -304.438" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1.5 0 0 1.06426 -160 -29.8163" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 110 -15" transformations="translations" pos="528 464" stroke="black" type="minipage" width="64" height="13.6632" depth="1.68" valign="top" size="small">\tiny\tt rf\_device[0]</text> +<path matrix="1.49204 0 0 1 -156.224 -64" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 109.571 -78" transformations="translations" pos="528 464" stroke="black" type="minipage" width="64" height="13.6632" depth="1.68" valign="top" size="small">\tiny\tt rf\_device[1]</text> +<path matrix="1.53737 0 0 1 -180.161 -304" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 107.571 -317" transformations="translations" pos="528 464" stroke="black" type="minipage" width="64" height="13.6632" depth="1.68" valign="top" size="small">\tiny\tt rf\_device[N-1]</text> +<path matrix="2.60074 0 0 1 -307.342 -22" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<path matrix="2.60024 0 0 1 -307.263 -118" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<path matrix="2.60024 0 0 1 -307.263 -214" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<text matrix="1 0 0 1 0 -33" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="24.4656" depth="12.528" valign="top" size="small" style="center">\tiny\tt common signal precoding(vCell)\\ PBCH,PSS/SSS,PCFICH/PHICH/PDCCH\\ +PDSCH - TM1-6</text> +<text matrix="1 0 0 1 0 -129" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="24.7944" depth="12.864" valign="top" size="small" style="center">\tiny\tt UE-specific signal precoding(vCell)\\ +UE-RS,PDSCH - TM7-10</text> +<text matrix="1 0 0 1 0 -243" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="10.9584" depth="0" valign="top" size="small" style="center">\tiny\tt PMCH precoding</text> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 288 l +</path> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 192 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +191.982 288.048 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +191.982 192.084 l +</path> +<path stroke="black"> +145 157.44 m +192 384 l +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 157.44 m +191.982 288.048 l +</path> +<path stroke="black" arrow="normal/normal"> +145 157.44 m +191.982 192.084 l +</path> +<path stroke="black" arrow="normal/normal"> +400 384 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 431.796 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 383.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 127.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400 288 m +449 383.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 127.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400 192 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +448.966 431.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 127.637 l +</path> +<text matrix="0 1 -1 0 517.304 -343.285" pos="596 32" stroke="black" type="label" width="116.59" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny phy\_vars\_eNB.txdataF</text> +<text matrix="0 1 -1 0 569.304 -343.285" pos="596 32" stroke="black" type="label" width="109.325" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny phy\_vars\_eNB.txdata</text> +<path matrix="1 0 0 1 -176 -16" stroke="black" arrow="normal/tiny"> +632 264.556 m +671.833 265 l +</path> +<text matrix="0 1 -1 0 779.067 -428.933" pos="636 280" stroke="black" type="minipage" width="84" height="16.6824" depth="4.704" valign="top" size="small" style="center">\setstretch{.5}\tt\tiny do\_ofdm\_mod\_rt()\par 36.211</text> +</page> +<page> +<layer name="alpha"/> +<view layers="alpha" active="alpha"/> +<text layer="alpha" matrix="1 0 0 1 199 -16" transformations="translations" pos="176 556" stroke="black" type="label" width="499.453" height="20.9244" depth="6.972" halign="center" valign="baseline">TX Precoding (to IF device, NGFI\_IFv4p5)</text> +<path matrix="1 0 0 1 -63 0" stroke="black" fill="lightgray"> +208 480 m +208 80 l +512 80 l +512 480 l +h +</path> +<path matrix="1 0 0 1 -63 -35" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 -63 -99" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 -63 -291" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<text matrix="1 0 0 1 -63 -15" transformations="translations" pos="96 464" stroke="black" type="minipage" width="89.789" height="15.2856" depth="3.312" valign="top" size="small">\tt eNB[0]</text> +<text matrix="1 0 0 1 -63 -79" transformations="translations" pos="96 464" stroke="black" type="minipage" width="97.789" height="15.2856" depth="3.312" valign="top" size="small">\tt eNB[1]</text> +<text matrix="1 0 0 1 -89.2484 -270.814" transformations="translations" pos="96 464" stroke="black" type="minipage" width="137.789" height="15.2856" depth="3.312" valign="top" size="small">\tt eNB[CC\_max]</text> +<path matrix="1 0 0 1 320.037 -0.368" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 320.714 -64.365" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 320.714 -320.365" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 320.815 -16.205" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 320.816 -16.2378" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 320.816 -80.2378" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1 0 0 1 319.542 -304.438" stroke="black" arrow="normal/normal"> +128 448 m +208 448.44 l +</path> +<path matrix="1.5 0 0 1.06426 -264 -29.8163" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 6 -15" transformations="translations" pos="528 464" stroke="black" type="minipage" width="88" height="10.6272" depth="0" valign="top" size="small">\tiny\tt if\_device[0]</text> +<path matrix="1.49204 0 0 1 -260.224 -64" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 5.571 -78" transformations="translations" pos="528 464" stroke="black" type="minipage" width="88" height="10.6272" depth="0" valign="top" size="small">\tiny\tt if\_device[1]</text> +<path matrix="1.53737 0 0 1 -284.161 -304" stroke="black"> +528 464 m +528 416 l +592 416 l +592 464 l +h +</path> +<text matrix="1 0 0 1 3.571 -317" transformations="translations" pos="528 464" stroke="black" type="minipage" width="96" height="10.6272" depth="0" valign="top" size="small">\tiny\tt if\_device[N-1]</text> +<path matrix="2.60074 0 0 1 -307.342 -22" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<path matrix="2.60024 0 0 1 -307.263 -118" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<path matrix="2.60024 0 0 1 -307.263 -214" stroke="black" fill="lightblue"> +192 432 m +192 368 l +272 368 l +272 432 l +h +</path> +<text matrix="1 0 0 1 0 -33" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="24.4656" depth="12.528" valign="top" size="small" style="center">\tiny\tt common signal precoding(vCell)\\ PBCH,PSS/SSS,PCFICH/PHICH/PDCCH\\ +PDSCH - TM1-6</text> +<text matrix="1 0 0 1 0 -129" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="24.7944" depth="12.864" valign="top" size="small" style="center">\tiny\tt UE-specific signal precoding(vCell)\\ +UE-RS,PDSCH - TM7-10</text> +<text matrix="1 0 0 1 0 -243" transformations="translations" pos="192 432" stroke="black" type="minipage" width="208" height="10.9584" depth="0" valign="top" size="small" style="center">\tiny\tt PMCH precoding</text> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 288 l +</path> +<path stroke="black" arrow="normal/normal"> +145 413.44 m +192 192 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +191.982 288.048 l +</path> +<path stroke="black" arrow="normal/normal"> +145 349.44 m +191.982 192.084 l +</path> +<path stroke="black"> +145 157.44 m +192 384 l +192 384 l +</path> +<path stroke="black" arrow="normal/normal"> +145 157.44 m +191.982 288.048 l +</path> +<path stroke="black" arrow="normal/normal"> +145 157.44 m +191.982 192.084 l +</path> +<path stroke="black" arrow="normal/normal"> +400 384 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 431.796 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 383.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.059 384.077 m +449 127.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400 288 m +449 383.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 127.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400 192 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +449 447.637 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 288.002 m +448.966 431.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 367.763 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 143.57 l +</path> +<path stroke="black" arrow="normal/normal"> +400.001 192.005 m +449 127.637 l +</path> +<path stroke="black" cap="1"> +448 544 m +448 544 l +</path> +<path stroke="black" cap="1"> +432 544 m +432 544 l +</path> +<path matrix="1 0 0 1 0 8" stroke="black" arrow="normal/normal"> +624 432 m +672 432 l +</path> +<path matrix="1 0 0 1 0 -56" stroke="black" arrow="normal/normal"> +624 432 m +672 432 l +</path> +<path matrix="1 0 0 1 1 -296" stroke="black" arrow="normal/normal"> +624 432 m +672 432 l +</path> +<text matrix="1 0 0 1 -6 -14" transformations="translations" pos="672 464" stroke="black" type="label" width="68.7072" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny NGFI\_IFv4p5</text> +<text matrix="1 0 0 1 -6 -78" transformations="translations" pos="672 464" stroke="black" type="label" width="68.7072" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny NGFI\_IFv4p5</text> +<text matrix="1 0 0 1 -6 -318" transformations="translations" pos="672 464" stroke="black" type="label" width="68.7072" height="8.3232" depth="2.304" valign="baseline" size="small">\tiny NGFI\_IFv4p5</text> +</page> +</ipe> diff --git a/targets/DOCS/oai_L1_L2_procedures.pdf b/targets/DOCS/oai_L1_L2_procedures.pdf old mode 100755 new mode 100644 index 369efc3b479b960c74e89b7e73e427a15cea8de9..4e8059f503d8a4fedd634dc014c4f572275a5be8 Binary files a/targets/DOCS/oai_L1_L2_procedures.pdf and b/targets/DOCS/oai_L1_L2_procedures.pdf differ diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 45f69ca41401433c0142dab7d267e07c70f89c58..54693f43c81c4b2e75747d1766a13b60678224d3 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -596,13 +596,14 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1; do { recv_IF4p5(ru, &frame_tx, &subframe_tx, &packet_type, &symbol_number); - if ((subframe_select(fp,*subframe) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul); + if ((subframe_select(fp,subframe_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul); LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n", *subframe,subframe_select(fp,*subframe),frame_tx,subframe_tx,symbol_number); if (proc->first_tx != 0) { *frame = frame_tx; *subframe = subframe_tx; proc->first_tx = 0; + symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1; } else { AssertFatal(frame_tx == *frame, @@ -616,7 +617,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type); } while (symbol_mask != symbol_mask_full); - if (subframe_select(fp,*subframe) == SF_DL) stop_meas(&ru->rx_fhaul); + if (subframe_select(fp,subframe_tx) == SF_DL) stop_meas(&ru->rx_fhaul); proc->subframe_tx = subframe_tx; proc->frame_tx = frame_tx; @@ -871,7 +872,10 @@ static void* ru_thread_asynch_rxtx( void* param ) { // asynchronous receive from south (Mobipass) if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe); // asynchronous receive from north (RRU IF4/IF5) - else if (ru->fh_north_asynch_in) ru->fh_north_asynch_in(ru,&frame,&subframe); + else if (ru->fh_north_asynch_in) { + if (subframe_select(&ru->frame_parms,subframe)!=SF_UL) + ru->fh_north_asynch_in(ru,&frame,&subframe); + } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); } @@ -1322,8 +1326,11 @@ static void* ru_stats_thread(void* param) { if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - if (ru->fh_north_out) print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); - + if (ru->fh_north_out) { + print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + print_meas(&ru->compression,"compression",NULL,NULL); + print_meas(&ru->transport,"transport",NULL,NULL); + } } } return(NULL); @@ -1911,6 +1918,8 @@ void init_RU(char *rf_config_file) { ru->ifdevice.eth_params = &ru->eth_params; reset_meas(&ru->rx_fhaul); reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); printf("openair0_transport_init returns %d for ru_id %d\n",ret,ru_id); @@ -1934,6 +1943,8 @@ void init_RU(char *rf_config_file) { ru->ifdevice.eth_params = &ru->eth_params; reset_meas(&ru->rx_fhaul); reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); printf("openair0_transport_init returns %d for ru_id %d\n",ret,ru_id);