eNB_scheduler_ulsch.c 54.8 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


nikaeinn's avatar
nikaeinn committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22 23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
nikaeinn's avatar
nikaeinn committed
27

28
 *******************************************************************************/
nikaeinn's avatar
nikaeinn committed
29 30 31

/*! \file eNB_scheduler_ulsch.c
 * \brief eNB procedures for the ULSCH transport channel
32 33 34
 * \author Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
35
 * \version 1.0
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
 * @ingroup _mac

 */

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

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

#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"

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

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

66
#define ENABLE_MAC_PAYLOAD_DEBUG
67 68 69 70 71
#define DEBUG_eNB_SCHEDULER 1

// This table holds the allowable PRB sizes for ULSCH transmissions
uint8_t rb_table[33] = {1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,54,60,72,75,80,81,90,96,100};

gauthier's avatar
gauthier committed
72
void rx_sdu(
73 74 75
  const module_id_t enb_mod_idP,
  const int         CC_idP,
  const frame_t     frameP,
gauthier's avatar
gauthier committed
76
  const sub_frame_t subframeP,
77 78 79 80 81
  const rnti_t      rntiP,
  uint8_t          *sduP,
  const uint16_t    sdu_lenP,
  const int         harq_pidP,
  uint8_t          *msg3_flagP)
82 83 84 85 86 87 88 89 90 91 92 93 94
{

  unsigned char  rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
  unsigned char  rx_lcids[NB_RB_MAX];
  unsigned short rx_lengths[NB_RB_MAX];
  int    UE_id = find_UE_id(enb_mod_idP,rntiP);
  int ii,j;
  eNB_MAC_INST *eNB = &eNB_mac_inst[enb_mod_idP];
  UE_list_t *UE_list= &eNB->UE_list;

  start_meas(&eNB->rx_ulsch_sdu);

  if ((UE_id >  NUMBER_OF_UE_MAX) || (UE_id == -1)  )
95 96 97
    for(ii=0; ii<NB_RB_MAX; ii++) {
      rx_lengths[ii] = 0;
    }
98

gauthier's avatar
gauthier committed
99
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,1);
gauthier's avatar
gauthier committed
100
  if (opt_enabled == 1) {
nikaeinn's avatar
nikaeinn committed
101
    trace_pdu(0, sduP,sdu_lenP, 0, 3, rntiP,subframeP, 0,0);
gauthier's avatar
gauthier committed
102
    LOG_D(OPT,"[eNB %d][ULSCH] Frame %d  rnti %x  with size %d\n",
nikaeinn's avatar
nikaeinn committed
103
    		  enb_mod_idP, frameP, rntiP, sdu_lenP);
gauthier's avatar
gauthier committed
104
  }
105

106
  LOG_D(MAC,"[eNB %d] CC_id %d Received ULSCH sdu from PHY (rnti %x, UE_id %d), parsing header\n",enb_mod_idP,CC_idP,rntiP,UE_id);
107
  
108
  payload_ptr = parse_ulsch_header(sduP,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_lenP);
109 110 111 112
 
  eNB->eNB_stats[CC_idP].ulsch_bytes_rx=sdu_lenP;
  eNB->eNB_stats[CC_idP].total_ulsch_bytes_rx+=sdu_lenP;
  eNB->eNB_stats[CC_idP].total_ulsch_pdus_rx+=1;
113 114 115 116 117 118 119
  // control element
  for (i=0; i<num_ce; i++) {

    switch (rx_ces[i]) { // implement and process BSR + CRNTI +
    case POWER_HEADROOM:
      if (UE_id != -1) {
        UE_list->UE_template[CC_idP][UE_id].phr_info =  (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET;
120 121
        LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n",
              enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].phr_info);
122 123 124 125 126 127 128
        UE_list->UE_template[CC_idP][UE_id].phr_info_configured=1;
      }

      payload_ptr+=sizeof(POWER_HEADROOM_CMD);
      break;

    case CRNTI:
129
      UE_id = find_UE_id(enb_mod_idP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]);
130
      LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",enb_mod_idP, CC_idP, rx_ces[i], i,num_ce,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id);
131

roux's avatar
roux committed
132
      payload_ptr+=2;
133
      /* we don't process this CE yet */
roux's avatar
roux committed
134
      if (msg3_flagP != NULL) {
135
	*msg3_flagP = 0;
roux's avatar
roux committed
136
      }
137 138 139 140
      break;

    case TRUNCATED_BSR:
    case SHORT_BSR: {
141 142 143 144 145 146
      uint8_t lcgid;
      lcgid = (payload_ptr[0] >> 6);

      LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
	    enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f);

147
      if (UE_id  != -1) {
148

149 150
        UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f);

151
        if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] == 0 ) {
152
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid]=frameP;
153
        }
154
      }
155
      else {
156

157
      }
158
      payload_ptr += 1;//sizeof(SHORT_BSR); // fixme
159
    }
160
    break;
161

162 163 164 165 166 167 168 169
    case LONG_BSR:
      if (UE_id  != -1) {
        UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] = ((payload_ptr[0] & 0xFC) >> 2);
        UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] =
          ((payload_ptr[0] & 0x03) << 4) | ((payload_ptr[1] & 0xF0) >> 4);
        UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] =
          ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6);
        UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] = (payload_ptr[2] & 0x3F);
170
        LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = "
171
              "%u LCGID2 = %u LCGID3 = %u\n",
172
              enb_mod_idP, CC_idP,
173 174 175 176 177 178
              rx_ces[i],
              UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0],
              UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1],
              UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2],
              UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]);

179
        if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] == 0 ) {
180
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0]=0;
181
        } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0] == 0) {
182
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0]=frameP;
183
        }
184

185
        if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1] == 0 ) {
186
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1]=0;
187
        } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1] == 0) {
188
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID1]=frameP;
189
        }
190

191
        if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2] == 0 ) {
192
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2]=0;
193
        } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2] == 0) {
194
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID2]=frameP;
195
        }
196

197
        if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3] == 0 ) {
198
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3]= 0;
199
        } else if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3] == 0) {
200 201
          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID3]=frameP;

202
        }
203 204 205 206 207 208
      }

      payload_ptr += 3;////sizeof(LONG_BSR);
      break;

    default:
209
      LOG_E(MAC, "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n", enb_mod_idP, CC_idP, rx_ces[i]);
210 211 212 213 214 215 216 217 218
      break;
    }
  }

  for (i=0; i<num_sdu; i++) {
    LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);

    switch (rx_lcids[i]) {
    case CCCH :
219 220
      LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH:  %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n",
            enb_mod_idP,CC_idP,frameP,
221 222 223
            payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP);

      for (ii=0; ii<NB_RA_PROC_MAX; ii++) {
224
        LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), active %d\n",
225
              enb_mod_idP, CC_idP, ii,
226 227
              eNB->common_channels[CC_idP].RA_template[ii].rnti, rntiP,
              eNB->common_channels[CC_idP].RA_template[ii].RA_active);
228

229 230
        if ((eNB->common_channels[CC_idP].RA_template[ii].rnti==rntiP) &&
            (eNB->common_channels[CC_idP].RA_template[ii].RA_active==TRUE)) {
231

232
          //payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len);
233

234 235
          if (UE_id < 0) {
            memcpy(&eNB->common_channels[CC_idP].RA_template[ii].cont_res_id[0],payload_ptr,6);
knopp's avatar
knopp committed
236
            LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %d\n",
237
                  enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP);
238

239
            if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) {
240
              mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n");
kaltenbe's avatar
kaltenbe committed
241
	      // kill RA procedure
242
            } else
243 244
              LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n",
                    enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id);
245
          } else {
knopp's avatar
knopp committed
246
            LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %d\n",
247
                  enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP);
kaltenbe's avatar
kaltenbe committed
248
	    // kill RA procedure
249
          }
250

251
          if (Is_rrc_registered == 1)
252 253
            mac_rrc_data_ind(
              enb_mod_idP,
254
              CC_idP,
gauthier's avatar
gauthier committed
255
              frameP,subframeP,
256 257 258
              rntiP,
              CCCH,
              (uint8_t*)payload_ptr,
259
              rx_lengths[i],
260 261 262
              ENB_FLAG_YES,
              enb_mod_idP,
              0);
263 264


265 266 267
          if (num_ce >0) {  // handle msg3 which is not RRCConnectionRequest
            //  process_ra_message(msg3,num_ce,rx_lcids,rx_ces);
          }
268

269 270
          eNB->common_channels[CC_idP].RA_template[ii].generate_Msg4 = 1;
          eNB->common_channels[CC_idP].RA_template[ii].wait_ack_Msg4 = 0;
271

272 273
        } // if process is active
      } // loop on RA processes
274

275
      break;
276

277 278 279
    case  DCCH :
    case DCCH1 :
      //      if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){
280

281
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
282 283
      LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));

284
      for (j=0; j<32; j++) {
285
        LOG_T(MAC,"%x ",payload_ptr[j]);
286
      }
287 288

      LOG_T(MAC,"\n");
289
#endif
290

roux's avatar
roux committed
291 292 293 294 295 296 297
      if (UE_id != -1) {
        //  This check is just to make sure we didn't get a bogus SDU length, to be removed ...
        if (rx_lengths[i]<CCCH_PAYLOAD_SIZE_MAX) {
          LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n",
                enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]);

          mac_rlc_data_ind(
298 299 300 301 302 303 304 305 306 307 308
			   enb_mod_idP,
			   rntiP,
			   enb_mod_idP,
			   frameP,
			   ENB_FLAG_YES,
			   MBMS_FLAG_NO,
			   rx_lcids[i],
			   (char *)payload_ptr,
			   rx_lengths[i],
			   1,
			   NULL);//(unsigned int*)crc_status);
roux's avatar
roux committed
309 310 311 312
          UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
          UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
        }
      } /* UE_id != -1 */
313 314 315 316 317 318

      //      }
      break;

    case DTCH: // default DRB
      //      if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){
319

320
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
321
      LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));
322

323
      for (j=0; j<32; j++) {
324
        LOG_T(MAC,"%x ",payload_ptr[j]);
325
      }
326

327 328 329
      LOG_T(MAC,"\n");
#endif

330 331
      LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
            enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id,rx_lcids[i]);
332

roux's avatar
roux committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
      if (UE_id != -1) {
        if ((rx_lengths[i] <SCH_PAYLOAD_SIZE_MAX) &&  (rx_lengths[i] > 0) ) {   // MAX SIZE OF transport block
          mac_rlc_data_ind(
            enb_mod_idP,
            rntiP,
            enb_mod_idP,
            frameP,
            ENB_FLAG_YES,
            MBMS_FLAG_NO,
            DTCH,
            (char *)payload_ptr,
            rx_lengths[i],
            1,
            NULL);//(unsigned int*)crc_status);
          UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
          UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
        }
      } /* UE_id != -1 */
351 352 353 354 355

      //      }
      break;

    default :  //if (rx_lcids[i] >= DTCH) {
roux's avatar
roux committed
356 357
      if (UE_id != -1)
        UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1;
358 359
      LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ",
            enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
360
      break;
361
    }
362 363 364 365 366 367

    payload_ptr+=rx_lengths[i];
  }

  /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */
  if ((num_sdu == 0) && (num_ce==0)) {
roux's avatar
roux committed
368 369
    if (UE_id != -1)
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx+=1;
370 371 372

    if (msg3_flagP != NULL) {
      if( *msg3_flagP == 1 ) {
373
        LOG_N(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP);
374 375
        *msg3_flagP=0;
      }
376
    }
377
  } else {
roux's avatar
roux committed
378 379 380 381 382
    if (UE_id != -1) {
      UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx=sdu_lenP;
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx+=sdu_lenP;
      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx+=1;
    }
383 384
  }

gauthier's avatar
gauthier committed
385
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,0);
386
  stop_meas(&eNB->rx_ulsch_sdu);
387 388 389
}


390 391
uint32_t bytes_to_bsr_index(int32_t nbytes)
{
392

393
  uint32_t i=0;
394

395
  if (nbytes<0) {
396
    return(0);
397
  }
398

399 400 401 402 403 404
  while ((i<BSR_TABLE_SIZE)&&
         (BSR_TABLE[i]<=nbytes)) {
    i++;
  }

  return(i-1);
405 406
}

407
void adjust_bsr_info(int buffer_occupancy,
408
                     uint16_t TBS,
409 410 411 412 413 414 415 416 417 418 419 420 421
                     UE_TEMPLATE *UE_template)
{

  uint32_t         tmp_bsr;

  // could not serve all the uplink traffic
  if (buffer_occupancy > 0 ) {
    if (BSR_TABLE[UE_template->bsr_info[LCGID0]] <=  TBS ) {
      tmp_bsr = BSR_TABLE[UE_template->bsr_info[LCGID0]]; // serving this amout of  bytes
      UE_template->bsr_info[LCGID0] = 0;

      if (BSR_TABLE[UE_template->bsr_info[LCGID1]] <= (TBS-tmp_bsr)) {
        tmp_bsr += BSR_TABLE[UE_template->bsr_info[LCGID1]];
422
        UE_template->bsr_info[LCGID1] = 0;
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441

        if (BSR_TABLE[UE_template->bsr_info[LCGID2]] <= (TBS-tmp_bsr)) {
          tmp_bsr += BSR_TABLE[UE_template->bsr_info[LCGID2]];
          UE_template->bsr_info[LCGID2] = 0;

          if (BSR_TABLE[UE_template->bsr_info[LCGID3]] <= (TBS-tmp_bsr)) {
            tmp_bsr += BSR_TABLE[UE_template->bsr_info[LCGID3]];
            UE_template->bsr_info[LCGID3] = 0;
          } else {
            UE_template->bsr_info[LCGID3] = bytes_to_bsr_index((int32_t)BSR_TABLE[UE_template->bsr_info[LCGID3]] - ((int32_t) TBS - (int32_t)tmp_bsr));
          }
        } else {
          UE_template->bsr_info[LCGID2] = bytes_to_bsr_index((int32_t)BSR_TABLE[UE_template->bsr_info[LCGID2]] - ((int32_t)TBS - (int32_t)tmp_bsr));
        }
      } else {
        UE_template->bsr_info[LCGID1] = bytes_to_bsr_index((int32_t)BSR_TABLE[UE_template->bsr_info[LCGID1]] - ((int32_t)TBS - (int32_t)tmp_bsr));
      }
    } else {
      UE_template->bsr_info[LCGID0] = bytes_to_bsr_index((int32_t)BSR_TABLE[UE_template->bsr_info[LCGID0]] - (int32_t)TBS);
442
    }
443 444 445 446 447 448
  } else { // we have flushed all buffers so clear bsr
    UE_template->bsr_info[LCGID0] = 0;
    UE_template->bsr_info[LCGID1] = 0;
    UE_template->bsr_info[LCGID2] = 0;
    UE_template->bsr_info[LCGID3] = 0;
  }
449 450 451


}
452

453 454
void add_ue_ulsch_info(module_id_t module_idP, int CC_id, int UE_id, sub_frame_t subframeP, UE_ULSCH_STATUS status)
{
455

456 457 458
  eNB_ulsch_info[module_idP][CC_id][UE_id].rnti             = UE_RNTI(module_idP,UE_id);
  eNB_ulsch_info[module_idP][CC_id][UE_id].subframe         = subframeP;
  eNB_ulsch_info[module_idP][CC_id][UE_id].status           = status;
459

460
  eNB_ulsch_info[module_idP][CC_id][UE_id].serving_num++;
461 462 463

}

464 465 466
// This seems not to be used anymore
/*
int schedule_next_ulue(module_id_t module_idP, int UE_id, sub_frame_t subframeP){
467

468
  int next_ue;
469 470 471

  // first phase: scheduling for ACK
  switch (subframeP) {
472
    // scheduling for subframeP 2: for scheduled user during subframeP 5 and 6
473
  case 8:
474
    if  ((eNB_dlsch_info[module_idP][UE_id].status == S_DL_SCHEDULED) &&
475
   (eNB_dlsch_info[module_idP][UE_id].subframe == 5 || eNB_dlsch_info[module_idP][UE_id].subframe == 6)){
476 477 478
      // set the downlink status
      eNB_dlsch_info[module_idP][UE_id].status = S_DL_BUFFERED;
      return UE_id;
479 480 481 482
    }
    break;
    // scheduling for subframeP 3: for scheduled user during subframeP 7 and 8
  case 9:
483
    if  ((eNB_dlsch_info[module_idP][UE_id].status == S_DL_SCHEDULED) &&
484
   (eNB_dlsch_info[module_idP][UE_id].subframe == 7 || eNB_dlsch_info[module_idP][UE_id].subframe == 8)){
485 486
      eNB_dlsch_info[module_idP][UE_id].status = S_DL_BUFFERED;
      return UE_id;
487 488 489 490
    }
    break;
    // scheduling UL subframeP 4: for scheduled user during subframeP 9 and 0
  case 0 :
491
    if  ((eNB_dlsch_info[module_idP][UE_id].status == S_DL_SCHEDULED) &&
492
   (eNB_dlsch_info[module_idP][UE_id].subframe == 9 || eNB_dlsch_info[module_idP][UE_id].subframe == 0)){
493 494
      eNB_dlsch_info[module_idP][UE_id].status = S_DL_BUFFERED;
      return UE_id;
495 496 497 498 499 500 501 502 503
    }
    break;
  default:
    break;
  }

  // second phase
  for (next_ue=0; next_ue <NUMBER_OF_UE_MAX; next_ue++ ){

504 505 506 507 508
    if  (eNB_ulsch_info[module_idP][next_ue].status == S_UL_WAITING )
      return next_ue;
    else if (eNB_ulsch_info[module_idP][next_ue].status == S_UL_SCHEDULED){
      eNB_ulsch_info[module_idP][next_ue].status = S_UL_BUFFERED;
    }
509 510
  }
  for (next_ue=0; next_ue <NUMBER_OF_UE_MAX; next_ue++ ){
511 512
    if (eNB_ulsch_info[module_idP][next_ue].status != S_UL_NONE )// do this just for active UEs
      eNB_ulsch_info[module_idP][next_ue].status = S_UL_WAITING;
513 514 515 516 517
  }
  next_ue = 0;
  return next_ue;

}
518
 */
519 520 521 522 523 524





unsigned char *parse_ulsch_header(unsigned char *mac_header,
525 526 527 528 529
                                  unsigned char *num_ce,
                                  unsigned char *num_sdu,
                                  unsigned char *rx_ces,
                                  unsigned char *rx_lcids,
                                  unsigned short *rx_lengths,
530 531 532 533 534 535 536 537 538
                                  unsigned short tb_length)
{

  unsigned char not_done=1,num_ces=0,num_sdus=0,lcid,num_sdu_cnt;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length, ce_len=0;

  while (not_done==1) {

539
    if (((SCH_SUBHEADER_FIXED*)mac_header_ptr)->E == 0) {
540
      not_done = 0;
541
    }
542 543 544 545 546 547 548 549

    lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;

    if (lcid < EXTENDED_POWER_HEADROOM) {
      if (not_done==0) { // last MAC SDU, length is implicit
        mac_header_ptr++;
        length = tb_length-(mac_header_ptr-mac_header)-ce_len;

550
        for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) {
551
          length -= rx_lengths[num_sdu_cnt];
552
        }
553 554 555 556 557 558 559
      } else {
        if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;//sizeof(SCH_SUBHEADER_SHORT);
        } else { // F = 1
          length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
          mac_header_ptr += 3;//sizeof(SCH_SUBHEADER_LONG);
560
        }
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
      }

      LOG_D(MAC,"[eNB] sdu %d lcid %d tb_length %d length %d (offset now %d)\n",
            num_sdus,lcid,tb_length, length,mac_header_ptr-mac_header);
      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // This is a control element subheader POWER_HEADROOM, BSR and CRNTI
      if (lcid == SHORT_PADDING) {
        mac_header_ptr++;
      } else {
        rx_ces[num_ces] = lcid;
        num_ces++;
        mac_header_ptr++;

576
        if (lcid==LONG_BSR) {
577
          ce_len+=3;
578
        } else if (lcid==CRNTI) {
579
          ce_len+=2;
580
        } else if ((lcid==POWER_HEADROOM) || (lcid==TRUNCATED_BSR)|| (lcid== SHORT_BSR)) {
581
          ce_len++;
582
        } else {
583 584
          LOG_E(MAC,"unknown CE %d \n", lcid);
          mac_xface->macphy_exit("unknown CE");
585
        }
586
      }
587
    }
588
  }
589

590 591 592 593
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
594 595 596
}


597 598 599 600 601 602
void schedule_ulsch(module_id_t module_idP, 
		    frame_t frameP,
		    unsigned char cooperation_flag,
		    sub_frame_t subframeP, 
		    unsigned char sched_subframe) {

603 604


605 606 607
  uint16_t first_rb[MAX_NUM_CCs],i;
  int CC_id;
  eNB_MAC_INST *eNB=&eNB_mac_inst[module_idP];
608

609
  start_meas(&eNB->schedule_ulsch);
610 611


612
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
613

614
    first_rb[CC_id] = 1;
615

616 617 618 619
    // UE data info;
    // check which UE has data to transmit
    // function to decide the scheduling
    // e.g. scheduling_rslt = Greedy(granted_UEs, nb_RB)
620

621 622
    // default function for default scheduling
    //
623

624 625 626 627
    // output of scheduling, the UE numbers in RBs, where it is in the code???
    // check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3
    // Msg3 is using 1 PRB so we need to increase first_rb accordingly
    // not sure about the break (can there be more than 1 active RA procedure?)
628

629 630 631 632
    for (i=0; i<NB_RA_PROC_MAX; i++) {
      if ((eNB->common_channels[CC_id].RA_template[i].RA_active == TRUE) &&
          (eNB->common_channels[CC_id].RA_template[i].generate_rar == 0) &&
          (eNB->common_channels[CC_id].RA_template[i].Msg3_subframe == sched_subframe)) {
knopp's avatar
knopp committed
633
	//leave out first RB for PUCCH
634 635 636
        first_rb[CC_id]++;
        break;
      }
637
    }
knopp's avatar
knopp committed
638 639 640 641 642 643

    /*
    if (mac_xface->is_prach_subframe(&(mac_xface->lte_frame_parms),frameP,subframeP)) {
      first_rb[CC_id] = (mac_xface->get_prach_prb_offset(&(mac_xface->lte_frame_parms),
    */

644
  }
645

646
  schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe,first_rb);
647

648
#ifdef CBA
649
  schedule_ulsch_cba_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, first_rb);
650 651
#endif

652

653
  stop_meas(&eNB->schedule_ulsch);
654

655 656 657 658 659 660 661 662 663
}



void schedule_ulsch_rnti(module_id_t   module_idP,
                         unsigned char cooperation_flag,
                         frame_t       frameP,
                         sub_frame_t   subframeP,
                         unsigned char sched_subframe,
664 665 666 667 668 669 670 671 672 673 674 675 676
                         uint16_t     *first_rb)
{

  int                UE_id;
  uint8_t            aggregation    = 2;
  rnti_t             rnti           = -1;
  uint8_t            round          = 0;
  uint8_t            harq_pid       = 0;
  void              *ULSCH_dci      = NULL;
  LTE_eNB_UE_stats  *eNB_UE_stats   = NULL;
  DCI_PDU           *DCI_pdu;
  uint8_t                 status         = 0;
  uint8_t                 rb_table_index = -1;
knopp's avatar
knopp committed
677
  uint16_t                TBS = 0;
678 679 680 681 682
  int32_t                buffer_occupancy=0;
  uint32_t                cqi_req,cshift,ndi,mcs,rballoc,tpc;
  int32_t                 normalized_rx_power, target_rx_power=-90;
  static int32_t          tpc_accumulated=0;

683
  int n,CC_id = 0;
684 685 686 687 688 689 690 691 692 693 694 695 696
  eNB_MAC_INST      *eNB=&eNB_mac_inst[module_idP];
  UE_list_t         *UE_list=&eNB->UE_list;
  UE_TEMPLATE       *UE_template;
  int                rvidx_tab[4] = {0,2,3,1};
  LTE_DL_FRAME_PARMS   *frame_parms;


  //  LOG_I(MAC,"entering ulsch preprocesor\n");

  ulsch_scheduler_pre_processor(module_idP,
                                frameP,
                                subframeP,
                                first_rb,
697
                                aggregation);
698 699 700 701 702 703 704

  //  LOG_I(MAC,"exiting ulsch preprocesor\n");

  // loop over all active UEs
  for (UE_id=UE_list->head_ul; UE_id>=0; UE_id=UE_list->next_ul[UE_id]) {

    // don't schedule if Msg4 is not received yet
705
    if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) {
706
      continue;
707
    }
708 709 710

    rnti = UE_RNTI(module_idP,UE_id);

711
    if (rnti==NOT_A_RNTI) {
712
      LOG_W(MAC,"[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n", module_idP,frameP,subframeP,UE_id);
713 714
      continue;
    }
715

716 717 718 719 720 721
    // loop over all active UL CC_ids for this UE
    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
      // This is the actual CC_id in the list
      CC_id = UE_list->ordered_ULCCids[n][UE_id];
      frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
      eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
722

723 724 725 726 727
      if (eNB_UE_stats==NULL) {
        LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,CC_id);
        continue; // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
      }

728 729
      if (CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti)) {
        LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
730 731
        continue; // break;
      }
732

733
      //      printf("UE %d/%x is feasible, mode %s\n",UE_id,rnti,mode_string[eNB_UE_stats->mode]);
734

735
      if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel
736

737 738
        DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
        UE_template = &UE_list->UE_template[CC_id][UE_id];
739

740
        if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1) == -1 ) {
741
          LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
742 743 744 745 746
                module_idP,frameP,subframeP, UE_id, CC_id, rnti);
          //  NN --> RK: Don't schedule UE if we cannot get harq pid
          //should we continue or set harq_pid to 0?
          continue;
        } else
747 748
          LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d  round %d (rnti %x,mode %s)\n",
                module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,rnti,mode_string[eNB_UE_stats->mode]);
749

750
#undef EXMIMO_IOT
751
#ifndef EXMIMO_IOT
752 753 754

        if (((UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) || (round>0) || ((frameP%10)==0))
          // if there is information on bsr of DCCH, DTCH or if there is UL_SR, or if there is a packet to retransmit, or we want to schedule a periodic feedback every 10 frames
755
#else
756
        if (round==0)
757
#endif
758 759 760 761
        {
          // reset the scheduling request
          UE_template->ul_SR = 0;
          aggregation = process_ue_cqi(module_idP,UE_id); // =2 by default!!
762
          status = mac_eNB_get_rrc_status(module_idP,rnti);
763 764 765 766 767 768 769
          cqi_req = (status < RRC_CONNECTED)? 0:1;

          //power control
          //compute the expected ULSCH RX power (for the stats)

          // this is the normalized RX power and this should be constant (regardless of mcs
          normalized_rx_power = eNB_UE_stats->UL_rssi[0];
knopp's avatar
knopp committed
770
          target_rx_power = mac_xface->get_target_pusch_rx_power(module_idP,CC_id);
771 772

          // this assumes accumulated tpc
kaltenbe's avatar
kaltenbe committed
773
	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
774 775 776 777
	  int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
          if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
	      ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
	    {
knopp's avatar
knopp committed
778 779
	    UE_template->pusch_tpc_tx_frame=frameP;
	    UE_template->pusch_tpc_tx_subframe=subframeP;
780 781 782 783 784 785
            if (normalized_rx_power>(target_rx_power+1)) {
              tpc = 0; //-1
              tpc_accumulated--;
            } else if (normalized_rx_power<(target_rx_power-1)) {
              tpc = 2; //+1
              tpc_accumulated++;
786
            } else {
787
              tpc = 1; //0
788 789
            }
          } else {
790
            tpc = 1; //0
791
          }
792

793
	  if (tpc!=1) {
navid's avatar
navid committed
794
	    LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
795 796 797 798
		  module_idP,frameP,subframeP,harq_pid,tpc,
		  tpc_accumulated,normalized_rx_power,target_rx_power);
	  }

799 800 801 802 803
          // new transmission
          if (round==0) {

            ndi = 1-UE_template->oldNDI_UL[harq_pid];
            UE_template->oldNDI_UL[harq_pid]=ndi;
804 805 806
	    UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
	    UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
807 808
            mcs = cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS

809
            if (UE_template->pre_allocated_rb_table_index_ul >=0) {
810
              rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
811
            } else {
812
	      mcs=cmin (10, openair_daq_vars.target_ue_ul_mcs);
813
              rb_table_index=5; // for PHR
814
	    }
815 816 817 818 819 820 821 822 823 824

            UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
            buffer_occupancy = UE_template->ul_total_buffer;

            while ((rb_table[rb_table_index]>(frame_parms->N_RB_UL-1-first_rb[CC_id])) &&
                   (rb_table_index>0)) {
              rb_table_index--;
            }

            TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]);
825 826
	    UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index];
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=TBS;
827 828 829 830 831 832 833 834 835
            buffer_occupancy -= TBS;
            rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
                                            first_rb[CC_id],
                                            rb_table[rb_table_index]);
            // increment for next UE allocation
            first_rb[CC_id]+=rb_table[rb_table_index];
            //store for possible retransmission
            UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];

836 837
            LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
                  module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
838 839 840 841 842 843 844 845 846 847 848
                  first_rb[CC_id],rb_table[rb_table_index],
                  rb_table_index,TBS,harq_pid);
            // Adjust BSR entries for LCGIDs
            adjust_bsr_info(buffer_occupancy,
                            TBS,
                            UE_template);

          } else if (round > 0) { //we schedule a retransmission

            ndi = UE_template->oldNDI_UL[harq_pid];

849
            if ((round&3)==0) {
850
              mcs = openair_daq_vars.target_ue_ul_mcs;
851
            } else {
852 853
              mcs = rvidx_tab[round&3] + 28; //not correct for round==4!

854
            }
855

856
            LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, harq_pid %d, round %d)\n",
857
                  module_idP,UE_id,rnti,CC_id,frameP,subframeP,mcs,
858
                  first_rb[CC_id],UE_template->nb_rb_ul[harq_pid],
859
		  harq_pid, round);
860 861 862 863 864

            rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
                                            first_rb[CC_id],
                                            UE_template->nb_rb_ul[harq_pid]);
            first_rb[CC_id]+=UE_template->nb_rb_ul[harq_pid];  // increment for next UE allocation
865 866 867 868 869 870 871
         
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission_rx+=1;
	    UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx=UE_template->nb_rb_ul[harq_pid];
	    UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=UE_template->nb_rb_ul[harq_pid];
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=mcs;
	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
	  }
872 873 874

          // Cyclic shift for DM RS
          if(cooperation_flag == 2) {
875
            if(UE_id == 1) { // For Distriibuted Alamouti, cyclic shift applied to 2nd UE
876
              cshift = 1;
877
            } else {
878
              cshift = 0;
879 880
            }
          } else {
881
            cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
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 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088

          if (frame_parms->frame_type == TDD) {
            switch (frame_parms->N_RB_UL) {
            case 6:
              ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
              ((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_1_5MHz_TDD_1_6_t),
                              aggregation,
                              sizeof_DCI0_1_5MHz_TDD_1_6_t,
                              format0,
                              0);
              break;

            default:
            case 25:
              ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
              ((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_5MHz_TDD_1_6_t),
                              aggregation,
                              sizeof_DCI0_5MHz_TDD_1_6_t,
                              format0,
                              0);
              break;

            case 50:
              ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_10MHz_TDD_1_6_t),
                              aggregation,
                              sizeof_DCI0_10MHz_TDD_1_6_t,
                              format0,
                              0);
              break;

            case 100:
              ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
              ((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_20MHz_TDD_1_6_t),
                              aggregation,
                              sizeof_DCI0_20MHz_TDD_1_6_t,
                              format0,
                              0);
              break;
            }
          } // TDD
          else { //FDD
            switch (frame_parms->N_RB_UL) {
            case 25:
            default:

              ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->type     = 0;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_5MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_5MHz_FDD_t),
                              aggregation,
                              sizeof_DCI0_5MHz_FDD_t,
                              format0,
                              0);
              break;

            case 6:
              ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->type     = 0;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_1_5MHz_FDD_t),
                              aggregation,
                              sizeof_DCI0_1_5MHz_FDD_t,
                              format0,
                              0);
              break;

            case 50:
              ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->type     = 0;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_10MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_10MHz_FDD_t),
                              aggregation,
                              sizeof_DCI0_10MHz_FDD_t,
                              format0,
                              0);
              break;

            case 100:
              ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];

              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->type     = 0;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->padding  = 0;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
              ((DCI0_20MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;

              add_ue_spec_dci(DCI_pdu,
                              ULSCH_dci,
                              rnti,
                              sizeof(DCI0_20MHz_FDD_t),
                              aggregation,
                              sizeof_DCI0_20MHz_FDD_t,
                              format0,
                              0);
              break;

            }
          }

          add_ue_ulsch_info(module_idP,
                            CC_id,
                            UE_id,
                            subframeP,
                            S_UL_SCHEDULED);

1089
          LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id);
1090
#ifdef DEBUG
1091
          dump_dci(frame_parms, &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]);
1092
#endif
1093

1094 1095 1096 1097
        } // UE_is_to_be_scheduled
      } // UE is in PUSCH
    } // loop over UE_id
  } // loop of CC_id
1098 1099 1100
}

#ifdef CBA
1101
void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, uint16_t *first_rb)
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
{

  eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP];
  UE_list_t         *UE_list=&eNB->UE_list;
  //UE_TEMPLATE       *UE_template;
  void              *ULSCH_dci      = NULL;
  DCI_PDU *DCI_pdu;
  uint8_t CC_id=0;
  uint8_t rb_table_index=0, aggregation=2;
  uint32_t rballoc;
  uint8_t cba_group, cba_resources;
  uint8_t required_rbs[NUM_MAX_CBA_GROUP];
  int8_t num_cba_resources[NUM_MAX_CBA_GROUP];// , weight[NUM_MAX_CBA_GROUP]
  // the following vars should become a vector [MAX_NUM_CCs]
  LTE_DL_FRAME_PARMS   *frame_parms;
  int8_t available_rbs=0;
  uint8_t remaining_rbs=0;
  uint8_t allocated_rbs=0;
  uint8_t total_UEs=UE_list->num_UEs;
  uint8_t active_UEs[NUM_MAX_CBA_GROUP];
  uint8_t total_groups=eNB_mac_inst[module_idP].common_channels[CC_id].num_active_cba_groups;
  int     min_rb_unit=2;
  uint8_t cba_policy=CBA_ES;
  int     UE_id;
  uint8_t mcs[NUM_MAX_CBA_GROUP];
  uint32_t total_cba_resources=0;
  uint32_t total_rbs=0;
  // We compute the weight of each group and initialize some variables

  // loop over all active UEs
  //  for (UE_id=UE_list->head_ul;UE_id>=0;UE_id=UE_list->next_ul[UE_id]) {

  for (cba_group=0; cba_group<total_groups; cba_group++) {
    // UEs in PUSCH with traffic
    //    weight[cba_group] = 0;
    required_rbs[cba_group] = 0;
    num_cba_resources[cba_group]=0;
    active_UEs[cba_group]=0;
    mcs[cba_group]=openair_daq_vars.target_ue_ul_mcs;
  }

  //LOG_D(MAC, "[eNB ] CBA granted ues are %d\n",granted_UEs );

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1146

1147 1148 1149 1150 1151
    frame_parms=mac_xface->get_lte_frame_parms(module_idP,CC_id);
    available_rbs=frame_parms->N_RB_DL-1-first_rb[CC_id];
    remaining_rbs=available_rbs;
    total_groups=eNB_mac_inst[module_idP].common_channels[CC_id].num_active_cba_groups;
    min_rb_unit=get_min_rb_unit(module_idP,CC_id);
1152

1153 1154
    if (available_rbs  < min_rb_unit )
      continue;
1155

1156 1157 1158 1159
    // remove this condition later
    // cba group template uses the exisitng UE template, and thus if a UE
    // is scheduled, the correspodning group can't be used for CBA
    // this can be fixed later
1160
    if (total_groups > 0)  {
1161 1162 1163
      DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;

      for (cba_group=0;
1164
           (cba_group<total_groups)   > (1<<aggregation));
1165 1166 1167 1168 1169
           cba_group++) {
        // equal weight
        //weight[cba_group] = floor(total_UEs/active_groups);//find_num_active_UEs_in_cbagroup(module_idP, cba_group);

        for (UE_id=UE_list->head_ul; UE_id>=0; UE_id=UE_list->next_ul[UE_id]) {
1170
          if (UE_RNTI(module_idP,UE_id)==NOT_A_RNTI)
1171 1172
            continue;

1173 1174 1175
          // simple UE identity based grouping
          if ((UE_id % total_groups) == cba_group) { // this could be simplifed to  active_UEs[UE_id % total_groups]++;
            if ((mac_get_rrc_status(module_idP,1,UE_id) > RRC_CONNECTED) &&