flexran_agent_scheduler_dlsch_ue.c 60.7 KB
Newer Older
1 2 3 4 5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */ 
21

22
/*! \file flexran_agent_scheduler_dlsch_ue.c
23
 * \brief procedures related to eNB for the DLSCH transport channel
24
 * \author Xenofon Foukas, Navid Nikaein and Raymond Knopp
25 26 27 28 29 30 31 32 33 34 35 36 37 38
 * \date 2016
 * \email: x.foukas@sms.ed.ac.uk
 * \version 0.1
 * @ingroup _mac

 */

#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

39
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
40 41 42 43 44 45 46 47 48 49 50 51
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

52
#include "ENB_APP/flexran_agent_defs.h"
53 54 55 56

#include "pdcp.h"

#include "header.pb-c.h"
57
#include "flexran.pb-c.h"
58
#include "flexran_agent_mac.h"
59
#include <dlfcn.h>
60 61 62 63 64 65 66 67 68

#include "SIMULATION/TOOLS/defs.h" // for taus

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

#define ENABLE_MAC_PAYLOAD_DEBUG

69 70 71 72
/**
 * Local variables to support slicing
 * 
 */
73

74

75 76 77 78 79 80 81
/*!\brief  UE ULSCH scheduling states*/
typedef enum {
  MIN_SLICE_STRATEGY = 0,
  SLICE_MASK,
  UEID_TO_SLICEID,
  MAX_SLICE_STRATEGY
} SLICING_STRATEGY;
82

83 84 85 86 87
// this assumes a max of of 16 UE per eNB/CC
#define SLICE0_MASK 0x000f 
#define SLICE1_MASK 0x00f0
#define SLICE2_MASK 0x0f00
#define SLICE3_MASK 0xf000
88 89


90 91 92
// number of active slices for  past and current time
int n_active_slices = 1;
int n_active_slices_current = 1;
93

94 95 96
// ue to slice mapping
int slicing_strategy = UEID_TO_SLICEID;
int slicing_strategy_current = UEID_TO_SLICEID;
97

98 99 100 101
// 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 total_slice_percentage = 0;
102

103 104 105
// 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};
106

Anta Huang's avatar
Anta Huang committed
107 108
int update_dl_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1};
int update_dl_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1};
109

110 111 112 113 114 115
// 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 
};
116

117 118
// pointer to the slice specific scheduler 
slice_scheduler slice_sched[MAX_NUM_SLICES] = {0};
119 120


121 122 123 124
/**
 * preprocessor functions for scheduling
 *
 */
125

126

127 128
// This function stores the downlink buffer for all the logical channels
void _store_dlsch_buffer (module_id_t Mod_id,
129
			  int         slice_id,
130 131
			  frame_t     frameP,
			  sub_frame_t subframeP)
132 133
{

134 135
  int                   UE_id,i;
  rnti_t                rnti;
136
  mac_rlc_status_resp_t rlc_status;
137 138
  UE_list_t             *UE_list = &eNB_mac_inst[Mod_id].UE_list;
  UE_TEMPLATE           *UE_template;
139

140 141 142
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
    
143 144 145
    if (flexran_slice_member(UE_id, slice_id) == 0)
      continue;
    
146
    UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id];
Xenofon Foukas's avatar
Xenofon Foukas committed
147

148 149 150
    // clear logical channel interface variables
    UE_template->dl_buffer_total = 0;
    UE_template->dl_pdus_total = 0;
151

152 153 154 155 156 157
    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;
    }
158

159
    rnti = UE_RNTI(Mod_id,UE_id);
160

161
    for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
162

163 164 165 166 167
      rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0
#ifdef Rel14
                                     ,0, 0
#endif
                                     );
168 169 170 171 172 173 174 175 176
      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];
177

178
#ifdef DEBUG_eNB_SCHEDULER
179

180 181 182 183 184
      /* 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,
185
              "[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 segmented %d \n",
186
              Mod_id, slice_id,frameP, subframeP, UE_id,
187 188 189 190 191
              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]
             );
192

193
#endif
194

195
    }
196

197 198 199 200 201 202 203
    //#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
           );
204

205 206 207
    //#endif
  }
}
208

209

210 211
// This function returns the estimated number of RBs required by each UE for downlink scheduling
void _assign_rbs_required (module_id_t Mod_id,
212 213 214 215 216 217
			   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])
218
{
219 220


221 222 223 224 225 226
  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;
227

228
  // clear rb allocations across all CC_ids
229 230
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
231 232 233 234
    
    if (flexran_slice_member(UE_id, slice_id) == 0)
      continue;
    
235 236
    pCCid = UE_PCCID(Mod_id,UE_id);
    rnti = UE_list->UE_template[pCCid][UE_id].rnti;
Xenofon Foukas's avatar
Xenofon Foukas committed
237

238 239 240 241
    /* skip UE not present in PHY (for any of its active CCs) */
    if (!phy_stats_exist(Mod_id, rnti))
      continue;

242 243 244 245
    //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);
246
      eNB_UE_stats[CC_id]->dlsch_mcs1 = cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
247
    }
248

249 250 251 252
    // 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 );
Xenofon Foukas's avatar
Xenofon Foukas committed
253

254 255 256 257 258 259
        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;
        }
260
      }
261
    }
262

263 264 265 266 267
    /* 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);
268

269 270 271
      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);
272

273
        if (cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)] == 0) {//eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
274 275 276 277
          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];
        }
278

279
        TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]);
280 281
	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));
282
        LOG_D(MAC,"[preprocessor] start RB assignment for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
283
              UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
284
              nb_rbs_required[CC_id][UE_id], flexran_get_ue_wcqi(Mod_id, UE_id), TBS);
285

286 287 288
        /* 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];
289

290
          if (nb_rbs_required[CC_id][UE_id] > nb_rbs_allowed_slice[CC_id][slice_id]) {
291
            TBS = mac_xface->get_TBS_DL(flexran_get_ue_wcqi(Mod_id, UE_id), nb_rbs_allowed_slice[CC_id][slice_id]);
292
            nb_rbs_required[CC_id][UE_id] = nb_rbs_allowed_slice[CC_id][slice_id];
293
            break;
294 295
          }

296
          TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]);
297
        } // end of while
Xenofon Foukas's avatar
Xenofon Foukas committed
298

299
        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",
300
              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)]);
301 302 303 304 305
      }
    }
  }
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319
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];
320

321
  for(i=0; i<N_RBG; i++) {
322

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
    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;
350
	  }
351 352 353 354 355
	}
      } // dl_pow_off[CC_id][UE_id] ! = 0
    }
  }
}
356

357 358 359 360 361 362 363 364
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],
365
					   uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES],
366 367 368 369 370 371 372 373 374 375 376 377 378 379
					   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;
#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);
Xenofon Foukas's avatar
Xenofon Foukas committed
380

381 382 383 384 385 386 387
  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;
388 389
  for (i=0; i<n_active_slices;i++)
    nb_rbs_allowed_slice[CC_id][i] = 0;
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
#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;
#ifdef SF05_LIMIT
    // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors)
420

421 422 423 424 425 426 427 428 429 430
    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;
431
      }
432 433 434 435
    }
    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;
  }
436
}
437

438 439
// 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,
440 441 442 443 444
				     int      slice_id,
				     frame_t       frameP,
				     sub_frame_t   subframeP,
				     int           N_RBG[MAX_NUM_CCs],
				     int           *mbsfn_flag)
445 446
{

447
  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], total_ue_count;
448 449
  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
  int                     UE_id, i;
450 451
  uint8_t round = 0;
  uint8_t harq_pid = 0;
452 453
  uint16_t                ii,j;
  uint16_t                nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
454
  uint16_t                nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES];
455 456 457 458 459 460 461 462 463
  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};
464

465 466
  int transmission_mode = 0;
  UE_sched_ctrl *ue_sched_ctl;
467 468
  
  
469 470
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    
471 472 473 474 475 476 477 478
    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);
    
479 480 481
    for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
      if (UE_list->active[i] != TRUE) continue;

482 483 484
      UE_id = i;
      // Initialize scheduling information for all active UEs
      
485 486
      //if (flexran_slice_member(UE_id, slice_id) == 0)
      //continue;
487 488 489 490 491 492 493 494
      _dlsch_scheduler_pre_processor_reset(Mod_id,
					   UE_id,
					   CC_id,
					   frameP,
					   subframeP,
					   N_RBG[CC_id],
					   nb_rbs_required,
					   nb_rbs_required_remaining,
495
					   nb_rbs_allowed_slice, 
496 497 498 499 500 501 502
					   rballoc_sub,
					   MIMO_mode_indicator);

    }
  }
  
  // Store the DLSCH buffer for each logical channel
503
  _store_dlsch_buffer (Mod_id,slice_id,frameP,subframeP);
504 505

  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
506
  _assign_rbs_required (Mod_id,slice_id, frameP,subframeP,nb_rbs_required,nb_rbs_allowed_slice,min_rb_unit);
507 508

  // Sorts the user on the basis of dlsch logical channel buffer and CQI
509
  sort_UEs (Mod_id,frameP,subframeP);
510 511 512 513

  total_ue_count = 0;

  // loop over all active UEs
514
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) { 
515 516 517 518 519
    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;
520

521
    UE_id = i;
522 523 524 525
    
    if (flexran_slice_member(UE_id, slice_id) == 0)
      continue;
    
526
    if (!phy_stats_exist(Mod_id, rnti))
527 528 529 530 531
      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];
532
      ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice[CC_id][slice_id];
533 534
      flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);

535 536 537 538
      // if there is no available harq_process, skip the UE
      if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
        continue;

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
      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;
      }


555
      // hypotetical assignment
556 557 558
      /*
       * 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
559
       * priority. Concerning the hypothetical assignment, we should assign more
560 561 562 563 564 565 566
       * 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;
567 568
      } 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);
569 570 571 572 573 574 575 576 577 578
      } 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);
579
   
580 581 582 583 584 585 586 587 588
    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;

589 590 591
    if (flexran_slice_member(i, slice_id) == 0)
      continue;
    
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
    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]);

      }
    }
  }

  //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]) {
611 612 613 614
      
      if (flexran_slice_member(i, slice_id) == 0)
	continue;
      
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
      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;
640 641 642 643 644
	
	if (flexran_slice_member(UE_id, slice_id) == 0)
	  continue;
        
	for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
645 646 647 648 649 650 651 652
          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;
653

654 655 656
	  if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
	    continue;

657 658 659
	  if (!phy_stats_exist(Mod_id, rnti))
            continue;

660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
          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];
687 688 689
 
    if (flexran_slice_member(UE_id, slice_id) == 0)
      continue;
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705

    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];
706 707
        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]);
708 709 710 711 712 713 714
      }
    }
  }
}

#define SF05_LIMIT 1

715 716 717 718
/*
 * Main scheduling functions to support slicing
 *
 */
719

720 721 722 723 724 725 726
void
flexran_schedule_ue_spec_default(mid_t   mod_id,
				 uint32_t      frame,
				 uint32_t      subframe,
				 int           *mbsfn_flag,
				 Protocol__FlexranMessage **dl_info)
//------------------------------------------------------------------------------
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
{
  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];
771

772 773 774 775
	}
      } 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];
776 777 778

      }
    }
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
  
    // 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);

803
  }
804
  
805 806
}

807 808 809
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs){
  return  (uint16_t) floor(rb_percentage * total_rbs); 
}
810

811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
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
    }
    break;
  }
  
  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_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_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_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_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)
//------------------------------------------------------------------------------
945
{
946 947 948 949 950
  uint8_t               CC_id;
  int                   UE_id;
  int                   N_RBG[MAX_NUM_CCs];
  unsigned char         aggregation;
  mac_rlc_status_resp_t rlc_status;
951
  unsigned char         header_len = 0, header_len_last = 0, ta_len = 0;
952 953
  uint16_t              nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb;
  uint16_t              TBS, j, rnti;
954 955
  uint8_t         round            = 0;
  uint8_t         harq_pid         = 0;
956 957 958 959 960 961 962 963 964 965
  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;
966
  LTE_eNB_UE_stats     *eNB_UE_stats     = NULL;
967 968 969
  Protocol__FlexDlData *dl_data[NUM_MAX_UE];
  int num_ues_added = 0;
  int channels_added = 0;
970

971 972 973
  Protocol__FlexDlDci *dl_dci;
  Protocol__FlexRlcPdu *rlc_pdus[11];
  uint32_t ce_flags = 0;
974

975
  uint8_t            rballoc_sub[25];
976
  int i;
977 978 979 980 981
  uint32_t data_to_request;
  uint32_t dci_tbs;
  uint8_t ue_has_transmission = 0;
  uint32_t ndi;
  
982
#if 0
983 984 985
  
  if (UE_list->head==-1) {
    return;
986
  }
987
  
988 989
#endif

990 991
  start_meas(&eNB->schedule_dlsch);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
992

993
  //weight = get_ue_weight(module_idP,UE_id);
994
  aggregation = 1; // set to the maximum aggregation level
995 996

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
997 998 999 1000 1001 1002
    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]--;
1003
    
1004
    N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id);
1005

1006 1007 1008 1009 1010 1011
    // 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;
1012 1013
  }

1014
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
1015

1016 1017
   start_meas(&eNB->schedule_dlsch_preprocessor);
   _dlsch_scheduler_pre_processor(mod_id,
1018 1019 1020 1021 1022
				  slice_id,
				  frame,
				  subframe,
				  N_RBG,
				  mbsfn_flag);
1023 1024
   stop_meas(&eNB->schedule_dlsch_preprocessor);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
1025

1026 1027
   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);
1028

1029
    if (mbsfn_flag[CC_id]>0)
1030
      continue;
1031
    
1032
    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
1033
  
1034
      rnti = flexran_get_ue_crnti(mod_id, UE_id);
1035
      eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
1036
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
1037 1038 1039 1040 1041 1042 1043
      
      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;
      }
      
1044 1045 1046
      if (flexran_slice_member(UE_id, slice_id) == 0)
      	continue;
      
1047 1048 1049 1050 1051
      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;
      }
1052

1053
      switch(mac_xface->get_transmission_mode(mod_id,CC_id,rnti)){
1054 1055 1056
      case 1:
      case 2:
      case 7:
1057
	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
1058 1059 1060 1061
				      eNB_UE_stats->DL_cqi[0],
				      format1);
	break;
      case 3:
1062
	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
1063 1064 1065 1066
				      eNB_UE_stats->DL_cqi[0],
				      format2A);
	break;
      default:
1067
	LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(mod_id,CC_id,rnti));
1068 1069 1070
	aggregation = 2;
      }
     
1071 1072 1073 1074 1075 1076 1077 1078
      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;
1079 1080
      }

1081 1082 1083 1084 1085 1086 1087 1088
      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);
1089 1090
      }

1091
      channels_added = 0;
1092

1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
      // 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)];
1106
      //      LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs);
1107
      mcs = cmin(mcs,flexran_slice_maxmcs(slice_id));
1108
#ifdef EXMIMO
1109

1110 1111 1112 1113
       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);
       }
1114

1115
#endif
1116

1117 1118 1119 1120
      // 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;
1121 1122
      }

1123 1124 1125 1126
      /* 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); */
1127

1128 1129 1130
      dl_dci = (Protocol__FlexDlDci*) malloc(sizeof(Protocol__FlexDlDci));
      protocol__flex_dl_dci__init(dl_dci);
      dl_data[num_ues_added]->dl_dci = dl_dci;
1131

1132 1133 1134 1135 1136 1137 1138 1139
      
      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) {
1140

1141 1142
	LOG_D(FLEXRAN_AGENT, "There was a retransmission just now and the round was %d\n", round);

1143 1144 1145 1146 1147 1148
	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);
	}
1149

1150
	mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid];
1151

1152 1153 1154 1155 1156
	  // 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);
1157

1158 1159 1160 1161 1162 1163 1164 1165 1166
	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;
1167

1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
	    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;
	    }
	  }
1183

1184 1185 1186 1187 1188 1189 1190 1191
	  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];
	  }