flexran_agent_scheduler_dlsch_ue.c 62.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */ 
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"
shahab's avatar
shahab committed
53
#include "flexran_agent_ran_api.h"
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
// number of active slices for  past and current time
shahab's avatar
shahab committed
91
92
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
// RB share for each slice for past and current time
shahab's avatar
shahab committed
99
100
float slice_percentage[MAX_NUM_SLICES] = {1.0, 1.0, 0.0, 0.0};
float slice_percentage_current[MAX_NUM_SLICES] = {1.0, 1.0, 0.0, 0.0};
101
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
// pointer to the slice specific scheduler 
shahab's avatar
shahab committed
118
slice_scheduler_dl slice_sched_dl[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
      rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
164
165
166
167
168
169
170
171
172
      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];
173

174
#ifdef DEBUG_eNB_SCHEDULER
175

176
177
178
179
180
      /* 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,
181
182
              "[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,
183
184
185
186
187
              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]
             );
188

189
#endif
190

191
    }
192

193
194
195
196
197
198
199
    //#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
           );
200

201
202
203
    //#endif
  }
}
204

205

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


217
218
219
220
221
222
  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;
223

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

234
235
236
237
    /* skip UE not present in PHY (for any of its active CCs) */
    if (!phy_stats_exist(Mod_id, rnti))
      continue;

238
239
240
241
    //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);
242
      eNB_UE_stats[CC_id]->dlsch_mcs1 = cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
243
    }
244

245
246
247
248
    // 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
249

250
251
252
253
254
255
        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;
        }
256
      }
257
    }
258

259
260
261
262
263
    /* 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);
264

265
266
267
      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);
268

269
        if (cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)] == 0) {//eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
270
271
272
273
          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];
        }
274

275
        TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]);
276
277
	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));
278
279
        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,
280
              nb_rbs_required[CC_id][UE_id], flexran_get_ue_wcqi(Mod_id, UE_id), TBS);
281

282
283
284
        /* 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];
285

286
          if (nb_rbs_required[CC_id][UE_id] > nb_rbs_allowed_slice[CC_id][slice_id]) {
shahab's avatar
shahab committed
287
            TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_allowed_slice[CC_id][slice_id]);
288
            nb_rbs_required[CC_id][UE_id] = nb_rbs_allowed_slice[CC_id][slice_id];
289
            break;
290
291
          }

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

295
        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",
296
              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)]);
297
298
299
300
301
      }
    }
  }
}

302
303
304
305
306
307
308
309
310
311
312
313
314
315
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];
316

317
  for(i=0; i<N_RBG; i++) {
318

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

353
354
355
356
357
358
359
360
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],
361
					   uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES],
362
363
364
365
366
367
368
369
370
371
372
373
374
375
					   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
376

377
378
379
380
381
382
383
  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;
384
385
  for (i=0; i<n_active_slices;i++)
    nb_rbs_allowed_slice[CC_id][i] = 0;
386
387
388
389
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
#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)
416

417
418
419
420
421
422
423
424
425
426
    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;
427
      }
428
429
430
431
    }
    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;
  }
432
}
433

434
435
// 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,
436
437
438
439
440
				     int      slice_id,
				     frame_t       frameP,
				     sub_frame_t   subframeP,
				     int           N_RBG[MAX_NUM_CCs],
				     int           *mbsfn_flag)
441
442
{

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

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

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

    }
  }
  
shahab's avatar
shahab committed
498
  /* Store the DLSCH buffer for each logical channel for each UE */
499
  _store_dlsch_buffer (Mod_id,slice_id,frameP,subframeP);
500
501

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

  // Sorts the user on the basis of dlsch logical channel buffer and CQI
505
  sort_UEs (Mod_id,frameP,subframeP);
506
507
508
509

  total_ue_count = 0;

  // loop over all active UEs
510
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) { 
511
512
513
514
515
    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;
516

517
    UE_id = i;
518
519
520
521
    
    if (flexran_slice_member(UE_id, slice_id) == 0)
      continue;
    
522
    if (!phy_stats_exist(Mod_id, rnti))
523
524
525
526
527
      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];
528
      ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice[CC_id][slice_id];
shahab's avatar
shahab committed
529
      flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round, openair_harq_DL);
530

531
532
533
534
      // if there is no available harq_process, skip the UE
      if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
        continue;

535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
      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;
563
564
      } 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);
565
566
567
568
569
570
571
572
573
574
      } 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);
575
   
576
577
578
579
580
581
582
583
584
    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;

585
586
587
    if (flexran_slice_member(i, slice_id) == 0)
      continue;
    
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
    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]) {
607
608
609
610
      
      if (flexran_slice_member(i, slice_id) == 0)
	continue;
      
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
      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;
636
637
638
639
640
	
	if (flexran_slice_member(UE_id, slice_id) == 0)
	  continue;
        
	for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
641
642
          CC_id = UE_list->ordered_CCids[ii][UE_id];
	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
shahab's avatar
shahab committed
643
	  flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round, openair_harq_DL);	  
644
645
646
647
648
          rnti = UE_RNTI(Mod_id,UE_id);

          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
          if(rnti == NOT_A_RNTI)
            continue;
649

650
651
652
	  if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
	    continue;

653
654
655
	  if (!phy_stats_exist(Mod_id, rnti))
            continue;

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

    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];
702
703
        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]);
704
705
706
707
708
709
710
      }
    }
  }
}

#define SF05_LIMIT 1

711
/*
shahab's avatar
shahab committed
712
 * Main Downlink Slicing
713
714
 *
 */
715

716
void
shahab's avatar
shahab committed
717
flexran_schedule_ue_dl_spec_default(mid_t   mod_id,
718
719
720
721
722
				 uint32_t      frame,
				 uint32_t      subframe,
				 int           *mbsfn_flag,
				 Protocol__FlexranMessage **dl_info)
//------------------------------------------------------------------------------
723
724
725
726
727
728
729
730
731
{
  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 ) {
shahab's avatar
shahab committed
732
      slice_sched_dl[i] = dlsym(NULL, dl_scheduler_type[i]); 
733
734
735
736
737
738
739
740
741
742
743
744
      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);
shahab's avatar
shahab committed
745

746
	n_active_slices_current = n_active_slices;
shahab's avatar
shahab committed
747

748
749
750
751
752
753
754
755
      } 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]){
shahab's avatar
shahab committed
756
757
758
 //      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];
759
760
	  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]);
shahab's avatar
shahab committed
761

762
	  slice_percentage_current[i] = slice_percentage[i];
shahab's avatar
shahab committed
763

shahab's avatar
shahab committed
764
765
766
767
768
769
	// } 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]);
shahab's avatar
shahab committed
770

shahab's avatar
shahab committed
771
	//   slice_percentage[i]= slice_percentage_current[i];
772

shahab's avatar
shahab committed
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]);
shahab's avatar
shahab committed
776

shahab's avatar
shahab committed
777
	// slice_percentage[i]= slice_percentage_current[i];
778

shahab's avatar
shahab committed
779
      // }
780
    }
781
782
783
784
785
786
  
    // 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]);
shahab's avatar
shahab committed
787

788
	slice_maxmcs_current[i] = slice_maxmcs[i];
shahab's avatar
shahab committed
789

790
791
      } 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]);
shahab's avatar
shahab committed
792

793
	slice_maxmcs[i]= slice_maxmcs_current[i];
shahab's avatar
shahab committed
794

795
796
797
798
799
800
801
      }
    }
    
    // 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]);
shahab's avatar
shahab committed
802

803
      update_dl_scheduler_current[i] = update_dl_scheduler[i];
shahab's avatar
shahab committed
804
      
805
806
807
808
    }

    // 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);
shahab's avatar
shahab committed
809
    slice_sched_dl[i](mod_id, i, frame, subframe, mbsfn_flag,dl_info);
810

811
  }
812
  
813
814
}

815
816
817
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs){
  return  (uint16_t) floor(rb_percentage * total_rbs); 
}
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
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)

{
shahab's avatar
shahab committed
879
  flexran_schedule_ue_dl_spec_common(mod_id,
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
				  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)

{
shahab's avatar
shahab committed
897
  flexran_schedule_ue_dl_spec_common(mod_id,
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
				  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)
  
{
  
shahab's avatar
shahab committed
916
  flexran_schedule_ue_dl_spec_common(mod_id,
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
				  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)
  
{
  
shahab's avatar
shahab committed
935
  flexran_schedule_ue_dl_spec_common(mod_id,
936
937
938
939
940
941
942
943
944
945
				  slice_id,
				  frame,
				  subframe,
				  mbsfn_flag,
				  dl_info);
  
}

//------------------------------------------------------------------------------
void
shahab's avatar
shahab committed
946
flexran_schedule_ue_dl_spec_common(mid_t   mod_id,
947
948
949
950
951
952
				int           slice_id, 
				uint32_t      frame,
				uint32_t      subframe,
				int           *mbsfn_flag,
				Protocol__FlexranMessage **dl_info)
//------------------------------------------------------------------------------
953
{
954
955
956
957
958
  uint8_t               CC_id;
  int                   UE_id;
  int                   N_RBG[MAX_NUM_CCs];
  unsigned char         aggregation;
  mac_rlc_status_resp_t rlc_status;
959
  unsigned char         header_len = 0, header_len_last = 0, ta_len = 0;
960
961
  uint16_t              nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb;
  uint16_t              TBS, j, rnti;
962
963
  uint8_t         round            = 0;
  uint8_t         harq_pid         = 0;
964
965
966
967
968
969
970
971
972
973
  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;
974
  LTE_eNB_UE_stats     *eNB_UE_stats     = NULL;
975
976
977
  Protocol__FlexDlData *dl_data[NUM_MAX_UE];
  int num_ues_added = 0;
  int channels_added = 0;
978

979
980
981
  Protocol__FlexDlDci *dl_dci;
  Protocol__FlexRlcPdu *rlc_pdus[11];
  uint32_t ce_flags = 0;
982

983
  uint8_t            rballoc_sub[25];
984
  int i;
985
986
987
988
989
  uint32_t data_to_request;
  uint32_t dci_tbs;
  uint8_t ue_has_transmission = 0;
  uint32_t ndi;
  
990
#if 0
991
992
993
  
  if (UE_list->head==-1) {
    return;
994
  }
995
  
996
997
#endif

998
999
  start_meas(&eNB->schedule_dlsch);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
1000

1001
  //weight = get_ue_weight(module_idP,UE_id);
1002
  aggregation = 1; // set to the maximum aggregation level
1003
1004

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1005
1006
1007
1008
1009
1010
    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]--;
1011
    
1012
    N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id);
1013

1014
1015
1016
1017
1018
1019
    // 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;
1020
1021
  }

1022
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
1023

1024
1025
   start_meas(&eNB->schedule_dlsch_preprocessor);
   _dlsch_scheduler_pre_processor(mod_id,
1026
1027
1028
1029
1030
				  slice_id,
				  frame,
				  subframe,
				  N_RBG,
				  mbsfn_flag);
1031
1032
   stop_meas(&eNB->schedule_dlsch_preprocessor);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
1033

1034
1035
   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);
1036

1037
    if (mbsfn_flag[CC_id]>0)
1038
      continue;
1039
    
1040
    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
1041
  
1042
      rnti = flexran_get_ue_crnti(mod_id, UE_id);
1043
      eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
1044
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
1045
1046
      
      if (eNB_UE_stats==NULL) {
shahab's avatar
shahab committed
1047
1048
1049
1050

        	LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
                //  mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
        	continue;
1051
1052
      }
      
1053
1054
1055
      if (flexran_slice_member(UE_id, slice_id) == 0)
      	continue;
      
1056
1057
1058
1059
1060
      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;
      }
1061

1062
      switch(mac_xface->get_transmission_mode(mod_id,CC_id,rnti)){
1063
1064
1065
      case 1:
      case 2:
      case 7:
shahab's avatar
shahab committed
1066
        	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
1067
1068
				      eNB_UE_stats->DL_cqi[0],
				      format1);
shahab's avatar
shahab committed
1069
      	break;
1070
      case 3:
shahab's avatar
shahab committed
1071
        	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
1072
1073
				      eNB_UE_stats->DL_cqi[0],
				      format2A);
shahab's avatar
shahab committed
1074
      	break;
1075
      default:
shahab's avatar
shahab committed
1076
1077
        	LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(mod_id,CC_id,rnti));
        	aggregation = 2;
1078
1079
      }
     
1080
1081
      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)) {
shahab's avatar
shahab committed
1082
1083
1084
1085
1086
1087
1088

            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;
1089
1090
      }

1091
1092
1093
1094
1095
1096
1097
1098
      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);
1099
1100
      }

1101
      channels_added = 0;
1102

1103
1104
1105
1106
1107
1108
1109
1110
      // 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;
shahab's avatar
shahab committed
1111
            
shahab's avatar
shahab committed
1112
      flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round, openair_harq_DL);
1113
1114
      sdu_length_total=0;
      mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
1115
      //      LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs);
1116
      mcs = cmin(mcs,flexran_slice_maxmcs(slice_id));
shahab's avatar
shahab committed
1117
// #ifdef EXMIMO
1118

shahab's avatar
shahab committed
1119
1120
1121
1122
//        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);
//        }
1123

shahab's avatar
shahab committed
1124
// #endif
1125

shahab's avatar
shahab committed
1126
1127
      /*Get pre available resource blocks based on buffers*/ 
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
1128
1129
      // initializing the rb allocation indicator for each UE
       for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
shahab's avatar
shahab committed
1130
1131
1132

          UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
        	rballoc_sub[j] = 0;
1133
1134
      }

1135
1136
1137
1138
      /* 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); */
1139

1140
1141
1142
      dl_dci = (Protocol__FlexDlDci*) malloc(sizeof(Protocol__FlexDlDci));
      protocol__flex_dl_dci__init(dl_dci);
      dl_data[num_ues_added]->dl_dci = dl_dci;
1143

1144
1145
1146
1147
1148
1149
1150
1151
      
      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) {
1152

shahab's avatar
shahab committed
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
      	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 {
      	  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
      }
1219

shahab's avatar
shahab committed
1220
       else { /* This is a potentially new SDU opportunity */
1221
1222
1223
1224
1225
1226
	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->