eNB_scheduler.c 13.5 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 eNB_scheduler.c
23
 * \brief eNB scheduler top level function operates on per subframe basis
24 25
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
26
 * \email: navid.nikaein@eurecom.fr
27 28
 * \version 0.5
 * @ingroup _mac
29

30
 */
31

32
#include "assertions.h"
33 34 35 36 37 38 39 40
#include "PHY/defs.h"
#include "PHY/extern.h"

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

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
41

42 43 44 45 46 47
#include "LAYER2/MAC/proto.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"
48

49 50
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
51

52 53
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
54

55
#if defined(FLEXRAN_AGENT_SB_IF)
56
//Agent-related headers
57 58 59
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_mac_proto.h"
60
#endif
61

62 63
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
64 65
#endif

66 67
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
68

69
extern RAN_CONTEXT_t RC;
70

71 72 73 74 75 76
uint16_t pdcch_order_table[6] = {31,31,511,2047,2047,8191};

void check_ul_failure(module_id_t module_idP,int CC_id,int UE_id,
		      frame_t frameP, sub_frame_t subframeP) {

  UE_list_t                           *UE_list      = &RC.mac[module_idP]->UE_list;
77
  nfapi_dl_config_request_t           *DL_req       = &RC.mac[module_idP]->DL_req[0];
78 79 80 81 82 83 84 85 86 87 88 89 90
  uint16_t                            rnti          = UE_RNTI(module_idP,UE_id);
  eNB_UE_STATS                        *eNB_UE_stats = &RC.mac[module_idP]->UE_list.eNB_UE_stats[CC_id][UE_id];
  COMMON_channels_t                   *cc           = RC.mac[module_idP]->common_channels;

  // check uplink failure
  if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer>0)&&
      (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync==0)) {
    LOG_D(MAC,"UE %d rnti %x: UL Failure timer %d \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);
    if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent==0) {
      UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=1;
      
      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
      LOG_D(MAC,"UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d) \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);	    
91
      nfapi_dl_config_request_pdu_t* dl_config_pdu                    = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu]; 
92 93
      memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
94
      dl_config_pdu->pdu_size                                         = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
95 96 97 98 99 100 101 102 103
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level     = get_aggregation(get_bw_index(module_idP,CC_id),eNB_UE_stats->dl_cqi,format1A);
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                  = rnti;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type             = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power    = 6000; // equal to RS power
      
      AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >=0) && (cc[CC_id].mib->message.dl_Bandwidth<6),
		  "illegal dl_Bandwidth %d\n",(int)cc[CC_id].mib->message.dl_Bandwidth);
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
104 105 106
      DL_req[CC_id].dl_config_request_body.number_dci++;
      DL_req[CC_id].dl_config_request_body.number_pdu++;
     
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
      /* 
	 add_ue_spec_dci(&DL_req[CC_id],
	 rnti,
	 get_aggregation(get_tw_index(module_idP,CC_id),eNB_UE_stats->DL_cqi[0],format1A),
	 format1A,
	 NO_DLSCH);*/
    }
    else { // ra_pdcch_sent==1
      LOG_D(MAC,"UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",UE_id,rnti,UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);	    	    
      if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0)
	UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=0; // resend every 4 frames	      
    }
    
    UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++;
    // check threshold
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) {
      // inform RRC of failure and clear timer
      LOG_I(MAC,"UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti);
      mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti);
      UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
      UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1;
    }
  } // ul_failure_timer>0
  
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP);

void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP) {

  nfapi_dl_config_request_t *DL_req         = &eNB->DL_req[0];
  nfapi_ul_config_request_t *UL_req         = &eNB->UL_req[0];
  nfapi_hi_dci0_request_t   *HI_DCI0_req    = &eNB->HI_DCI0_req[0];
  nfapi_tx_request_t        *TX_req         = &eNB->TX_req[0];
  
  eNB->pdu_index[CC_idP]                                     = 0;
  DL_req[CC_idP].dl_config_request_body.number_pdcch_ofdm_symbols           = 1;
  DL_req[CC_idP].dl_config_request_body.number_dci                          = 0;
  DL_req[CC_idP].dl_config_request_body.number_pdu                          = 0;
  DL_req[CC_idP].dl_config_request_body.number_pdsch_rnti                   = 0;
  DL_req[CC_idP].dl_config_request_body.transmission_power_pcfich           = 6000;
  
  HI_DCI0_req[CC_idP].hi_dci0_request_body.sfnsf                            = subframeP + (frameP<<3);
  HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci                    = 0;
  
  UL_req[CC_idP].ul_config_request_body.number_of_pdus                      = 0;
  UL_req[CC_idP].ul_config_request_body.rach_prach_frequency_resources      = 0; // ignored, handled by PHY for now
  UL_req[CC_idP].ul_config_request_body.srs_present                         = 0; // ignored, handled by PHY for now
  TX_req[CC_idP].tx_request_body.number_of_pdus                 = 0;

}

159
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)  
160
{
161

Raymond Knopp's avatar
 
Raymond Knopp committed
162
  int mbsfn_status[MAX_NUM_CCs];
163
  protocol_ctxt_t   ctxt;
164

165
#if defined(ENABLE_ITTI)
166
  MessageDef   *msg_p;
167
  const char         *msg_name;
168 169
  instance_t    instance;
  int           result;
170
#endif
171
  int CC_id,i; //,next_i;
172
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
173
  rnti_t rnti;
174
  
175
  COMMON_channels_t         *cc             = RC.mac[module_idP]->common_channels;
176

177
  eNB_UE_STATS              *eNB_UE_stats;
178
#if defined(FLEXRAN_AGENT_SB_IF)
179
  Protocol__FlexranMessage *msg;
180
#endif
181

182
  
183
  //  LOG_I(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler (UE_list->head %d)\n",module_idP, frameP, subframeP,UE_list->head);
184

185
  start_meas(&RC.mac[module_idP]->eNB_scheduler);
186
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
187

188
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
189
    mbsfn_status[CC_id]=0;
190
    // clear vrb_map
191
    memset(cc[CC_id].vrb_map,0,100);
192

193
    // clear DL/UL info for new scheduling round
194
    clear_nfapi_information(RC.mac[module_idP],CC_id,frameP,subframeP);
195

Cedric Roux's avatar
Cedric Roux committed
196
#if defined(Rel10) || defined(Rel14)
197
    cc[CC_id].mcch_active =0;
198
#endif
199 200
    RC.mac[module_idP]->frame    = frameP;
    RC.mac[module_idP]->subframe = subframeP;
201 202
  }

Raymond Knopp's avatar
 
Raymond Knopp committed
203
  // refresh UE list based on UEs dropped by PHY in previous subframe
204 205
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] != TRUE) continue;
206

207 208 209 210
    rnti         = UE_RNTI(module_idP, i);
    CC_id        = UE_PCCID(module_idP, i);
    eNB_UE_stats = &RC.mac[module_idP]->UE_list.eNB_UE_stats[CC_id][i];

211 212 213 214
    if ((frameP==0)&&(subframeP==0)) {
      LOG_I(MAC,"UE  rnti %x : %s, PHR %d dB CQI %d\n", rnti,
            UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync",
            UE_list->UE_template[CC_id][i].phr_info,
215
            eNB_UE_stats->dl_cqi);
216
    }
217

218
    RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63;
219
    if (i==UE_list->head)
220
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]); 
221
    // increment this, it is cleared when we receive an sdu
222
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++;
223

224
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++;
225

226
    /*
227
      //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
228
#if defined(FLEXRAN_AGENT_S_IF)
229
      if (mac_agent_registered[module_idP]) {
230 231 232
	agent_mac_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
									  rnti,
									  PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
233
      }
234
#endif
235 236 237
}*/
    check_ul_failure(module_idP,CC_id,i,frameP,subframeP);

Raymond Knopp's avatar
 
Raymond Knopp committed
238
  }
239

240
#if defined(ENABLE_ITTI)
241

242
  do {
243 244
    // Checks if a message has been sent to MAC sub-task
    itti_poll_msg (TASK_MAC_ENB, &msg_p);
245

246 247 248
    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);
249

250 251 252 253
      switch (ITTI_MSG_ID(msg_p)) {
      case MESSAGE_TEST:
        LOG_D(MAC, "Received %s\n", ITTI_MSG_NAME(msg_p));
        break;
254

255 256 257 258
      case RRC_MAC_BCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_BCCH_DATA_REQ (msg_p).frame, RRC_MAC_BCCH_DATA_REQ (msg_p).enb_index);
259

260 261
        // TODO process BCCH data req.
        break;
262

263 264 265 266
      case RRC_MAC_CCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_CCCH_DATA_REQ (msg_p).frame, RRC_MAC_CCCH_DATA_REQ (msg_p).enb_index);
267

268 269
        // TODO process CCCH data req.
        break;
270

Cedric Roux's avatar
Cedric Roux committed
271
#if defined(Rel10) || defined(Rel14)
272

273 274 275 276
      case RRC_MAC_MCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d, mbsfn_sync_area %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_MCCH_DATA_REQ (msg_p).frame, RRC_MAC_MCCH_DATA_REQ (msg_p).enb_index, RRC_MAC_MCCH_DATA_REQ (msg_p).mbsfn_sync_area);
277

278 279 280
        // TODO process MCCH data req.
        break;
#endif
281

282 283 284
      default:
        LOG_E(MAC, "Received unexpected message %s\n", msg_name);
        break;
285
      }
286 287 288 289

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    }
290
  } while(msg_p != NULL);
291

292 293
#endif

294 295 296
/* #ifndef DISABLE_SF_TRIGGER */
/*   //Send subframe trigger to the controller */
/*   if (mac_agent_registered[module_idP]) { */
297
/*     agent_mac_xface[module_idP]->flexran_agent_send_sf_trigger(module_idP); */
298 299
/*   } */
/* #endif */
300
  
301
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
302
  pdcp_run(&ctxt);
303

304 305
  rrc_rx_tx(&ctxt,
            0, // eNB index, unused in eNB
306
            CC_id);
307

Cedric Roux's avatar
Cedric Roux committed
308
#if defined(Rel10) || defined(Rel14)
309 310

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
311
    if (cc[CC_id].MBMS_flag >0) {
312
      start_meas(&RC.mac[module_idP]->schedule_mch);
313
      mbsfn_status[CC_id] = schedule_MBMS(module_idP,CC_id,frameP,subframeP);
314
      stop_meas(&RC.mac[module_idP]->schedule_mch);
Raymond Knopp's avatar
 
Raymond Knopp committed
315
    }
316
  }
317

318
#endif
319

320 321 322
  // This schedules MIB
  if ((subframeP==0) && (frameP&3) == 0) schedule_mib(module_idP,frameP,subframeP);

323
  // This schedules SI for legacy LTE and eMTC
324 325
  schedule_SI(module_idP,frameP,subframeP);

326 327
  // This schedules Random-Access for legacy LTE and eMTC
  schedule_RA(module_idP,frameP,subframeP);
328

329
  // This schedules ULSCH in subframeP+k
330 331
  schedule_ulsch(module_idP,frameP,subframeP);

332
  // This schedules DLSCH in subframeP
333 334
  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);

335 336
  // Allocate CCEs and Msg3 for good after scheduling is done
  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
337
    allocate_CCEs(module_idP,CC_id,subframeP,0);
338 339
    check_and_add_msg3(module_idP,frameP,subframeP);
  }
340

341
#if defined(FLEXRAN_AGENT_SB_IF)
342 343 344
#ifndef DISABLE_CONT_STATS
  //Send subframe trigger to the controller
  if (mac_agent_registered[module_idP]) {
345
    agent_mac_xface[module_idP]->flexran_agent_send_update_mac_stats(module_idP);
346
  }
347
#endif
348 349
#endif

350

351
  stop_meas(&RC.mac[module_idP]->eNB_scheduler);
352
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
353

354
}
355 356 357