eNB_scheduler.c 33.8 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22

/*! \file 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
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
36

37
#include "LAYER2/MAC/mac_proto.h"
38 39 40 41 42
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
43

44
#include "RRC/LTE/rrc_extern.h"
45
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
46

47 48
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
49

50
//Agent-related headers
51 52
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
53

Wang Tsu-Han's avatar
Wang Tsu-Han committed
54 55 56
/* for fair round robin SCHED */
#include "eNB_scheduler_fairRR.h"

57
#if defined(ENABLE_ITTI)
58
#include "intertask_interface.h"
59 60
#endif

61 62
#include "assertions.h"

63 64
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
65

66
extern RAN_CONTEXT_t RC;
67
extern int phy_test;
68

69
uint16_t pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
70

71

72 73
void
schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
74
{
75 76


77 78 79 80 81 82 83 84 85 86 87
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  UE_list_t *UE_list = &eNB->UE_list;
  nfapi_ul_config_request_body_t *ul_req;
  int CC_id, UE_id;
  COMMON_channels_t *cc = RC.mac[module_idP]->common_channels;
  SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon;
  struct SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated;
  uint8_t TSFC;
  uint16_t deltaTSFC;		// bitmap
  uint8_t srs_SubframeConfig;
  
88 89 90
  // table for TSFC (Period) and deltaSFC (offset)
  const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} };	// Table 5.5.3.3-2 3GPP 36.211 FDD
  const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} };	// Table 5.5.3.3-2 3GPP 36.211 TDD
91
  
92
  uint16_t srsPeriodicity, srsOffset;
93
  
94
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
95 96 97 98
    soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon;
    // check if SRS is enabled in this frame/subframe
    if (soundingRS_UL_ConfigCommon) {
      srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
99
      if (cc[CC_id].tdd_Config == NULL) {	// FDD
100
	deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
101
	TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
102
      } else {		// TDD
103
	deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
104
	TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
105 106
      }
      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
107
      uint16_t tmp = (subframeP % TSFC);
108
      
109
      if ((1 << tmp) & deltaTSFC) {
110
	// This is an SRS subframe, loop over UEs
111 112
	for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
	  if (!RC.mac[module_idP]->UE_list.active[UE_id]) continue;
113 114 115
	  ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
	  // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
	  if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
116
	  
117 118 119
	  AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
		      "physicalConfigDedicated is null for UE %d\n",
		      UE_id);
120
	  
121
	  if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
122
	    if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
123 124 125 126 127 128 129
	      get_srs_pos(&cc[CC_id],
			  soundingRS_UL_ConfigDedicated->choice.
			  setup.srs_ConfigIndex,
			  &srsPeriodicity, &srsOffset);
	      if (((10 * frameP + subframeP) % srsPeriodicity) == srsOffset) {
		// Program SRS
		ul_req->srs_present = 1;
130 131 132 133 134 135 136 137 138 139 140 141 142
		nfapi_ul_config_request_pdu_t * ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
		memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
		ul_config_pdu->pdu_type =  NFAPI_UL_CONFIG_SRS_PDU_TYPE;
		ul_config_pdu->pdu_size =  2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu));
		ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
		ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
		ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;		//              ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
143
		//              ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
144 145
		RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
		RC.mac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
146
		ul_req->number_of_pdus++;
147 148
	      }	// if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
	    }	// if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
149 150 151 152 153
	  }		// if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
	}		// for (UE_id ...
      }			// if((1<<tmp) & deltaTSFC)
      
    }			// SRS config
154 155 156
  }
}

157 158
void
schedule_CSI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
159
{
160 161
  eNB_MAC_INST                   *eNB = RC.mac[module_idP];
  UE_list_t                      *UE_list = &eNB->UE_list;
162 163
  COMMON_channels_t              *cc;
  nfapi_ul_config_request_body_t *ul_req;
164 165 166 167
  int                            CC_id, UE_id;
  struct CQI_ReportPeriodic      *cqi_ReportPeriodic;
  uint16_t                       Npd, N_OFFSET_CQI;
  int                            H;
168

169
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
170 171

    cc = &eNB->common_channels[CC_id];
172 173
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
      if (!UE_list->active[UE_id]) continue;
174

175
      ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
176

Cedric Roux's avatar
Cedric Roux committed
177
      // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
178
      if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
Cedric Roux's avatar
Cedric Roux committed
179

180 181 182 183 184
      AssertFatal(UE_list->
		  UE_template[CC_id][UE_id].physicalConfigDedicated
		  != NULL,
		  "physicalConfigDedicated is null for UE %d\n",
		  UE_id);
185 186

      if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) {
187 188
	if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) != NULL
	    && (cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_release)) {
189 190
	  //Rel8 Periodic CQI/PMI/RI reporting

191 192
	  get_csi_params(cc, cqi_ReportPeriodic, &Npd,
			 &N_OFFSET_CQI, &H);
193

194 195
	  if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) {	// CQI opportunity
	    UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id] = (((frameP * 10) + subframeP) / Npd) % H;
196
	    // Program CQI
197 198 199
	    nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
	    memset((void *) ul_config_pdu, 0,
		   sizeof(nfapi_ul_config_request_pdu_t));
200
	    ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
201 202
	    ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
203
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
204
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
205
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
206 207
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], CC_id, cc,
															get_tmode(module_idP, CC_id, UE_id),
208 209
															cqi_ReportPeriodic);
	    ul_req->number_of_pdus++;
210
	    ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
211

212
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
213
	    // PUT rel10-13 UCI options here
214
#endif
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
	  } else
	    if ((cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
		&& ((((frameP * 10) + subframeP) % ((H * Npd) << (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex / 161))) == N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex % 161))) {	// RI opportunity
	      // Program RI
	      nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
	      memset((void *) ul_config_pdu, 0,
		     sizeof(nfapi_ul_config_request_pdu_t));
	      ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
	      ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
	      ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
	      ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = (cc->p_eNB == 2) ? 1 : 2;
	      RC.mac[module_idP]->UL_req[CC_id].sfn_sf                                         = (frameP << 4) + subframeP;
	      ul_req->number_of_pdus++;
	      ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
	    }
	}		// if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) {
      }			// if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig)
    }			// for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
  }				// for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
237 238
}

239 240
void
schedule_SR(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
241
{
242 243 244 245 246 247
  eNB_MAC_INST                   *eNB = RC.mac[module_idP];
  UE_list_t                      *UE_list = &eNB->UE_list;
  nfapi_ul_config_request_t      *ul_req;
  nfapi_ul_config_request_body_t *ul_req_body;
  int                            CC_id;
  int                            UE_id;
248
  SchedulingRequestConfig_t      *SRconfig;
249 250 251 252
  int                            skip_ue;
  int                            is_harq;
  nfapi_ul_config_sr_information sr;
  int                            i;
253

254 255
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
256

257 258
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
      if (!RC.mac[module_idP]->UE_list.active[UE_id]) continue;
259

260 261
      ul_req        = &RC.mac[module_idP]->UL_req[CC_id];
      ul_req_body   = &ul_req->ul_config_request_body;
262

263
      // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
      if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;

      AssertFatal(UE_list->
		  UE_template[CC_id][UE_id].physicalConfigDedicated!= NULL,
		  "physicalConfigDedicated is null for UE %d\n",
		  UE_id);

      if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) {
	if (SRconfig->present == SchedulingRequestConfig_PR_setup) {
	  if (SRconfig->choice.setup.sr_ConfigIndex <= 4) {	// 5 ms SR period
	    if ((subframeP % 5) != SRconfig->choice.setup.sr_ConfigIndex) continue;
	  } else if (SRconfig->choice.setup.sr_ConfigIndex <= 14) {	// 10 ms SR period
	    if (subframeP != (SRconfig->choice.setup.sr_ConfigIndex - 5)) continue;
	  } else if (SRconfig->choice.setup.sr_ConfigIndex <= 34) {	// 20 ms SR period
	    if ((10 * (frameP & 1) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 15)) continue;
	  } else if (SRconfig->choice.setup.sr_ConfigIndex <= 74) {	// 40 ms SR period
	    if ((10 * (frameP & 3) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 35)) continue;
	  } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) {	// 80 ms SR period
	    if ((10 * (frameP & 7) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 75)) continue;
	  }
	}		// SRconfig->present == SchedulingRequestConfig_PR_setup)
      }			// SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL)
286 287 288

      // if we get here there is some PUCCH1 reception to schedule for SR

289
      skip_ue = 0;
290
      is_harq = 0;
291
      // check that there is no existing UL grant for ULSCH which overrides the SR
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
      for (i = 0; i < ul_req_body->number_of_pdus; i++) {
	if (((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) || 
	     (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) || 
	     (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) || 
	     (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)) && 
	    (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) {
	  skip_ue = 1;
	  break;
	}
	/* if there is already an HARQ pdu, convert to SR_HARQ */
	else if ((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) && 
		 (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) {
	  is_harq = 1;
	  break;
	}
307
      }
308 309

      // drop the allocation because ULSCH with handle it with BSR
310
      if (skip_ue == 1) continue;
311

312
      LOG_D(MAC,"Frame %d, Subframe %d : Scheduling SR for UE %d/%x is_harq:%d\n",frameP,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].rnti, is_harq);
313 314

      // check Rel10 or Rel8 SR
315
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
316 317 318 319 320 321 322
      if ((UE_list-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2)
	  && (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)
	  && (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) {
	sr.sr_information_rel10.tl.tag                    = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
	sr.sr_information_rel10.number_of_pucch_resources = 1;
	sr.sr_information_rel10.pucch_index_p1            = *UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10;
	LOG_D(MAC,"REL10 PUCCH INDEX P1:%d\n", sr.sr_information_rel10.pucch_index_p1);
323
      } else
324
#endif
325 326 327 328 329
	{
	  sr.sr_information_rel8.tl.tag                   = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
	  sr.sr_information_rel8.pucch_index              = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
	  LOG_D(MAC,"REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index);
	}
330 331 332

      /* if there is already an HARQ pdu, convert to SR_HARQ */
      if (is_harq) {
333 334 335 336
	nfapi_ul_config_harq_information h                                                                                 = ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.harq_information;
	ul_req_body->ul_config_pdu_list[i].pdu_type                                                                        = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
	ul_req_body->ul_config_pdu_list[i].uci_sr_harq_pdu.sr_information                                                  = sr;
	ul_req_body->ul_config_pdu_list[i].uci_sr_harq_pdu.harq_information                                                = h;
337
      } else {
338 339 340 341 342 343 344 345 346 347 348
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].pdu_type                                              = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE;
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.tl.tag  = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti    = UE_list->UE_template[CC_id][UE_id].rnti;
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel11.tl.tag = 0;
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel13.tl.tag = 0;
	ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.sr_information                             = sr;
	ul_req_body->number_of_pdus++;
      }			/* if (is_harq) */
      ul_req_body->tl.tag                                                                                                  = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
    }			// for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id])
  }				// for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
349 350
}

351 352
extern uint8_t nfapi_mode;

353 354 355
void
check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
		 frame_t frameP, sub_frame_t subframeP)
356
{
357 358 359 360
  UE_list_t                 *UE_list = &RC.mac[module_idP]->UE_list;
  nfapi_dl_config_request_t  *DL_req = &RC.mac[module_idP]->DL_req[0];
  uint16_t                      rnti = UE_RNTI(module_idP, UE_id);
  COMMON_channels_t              *cc = RC.mac[module_idP]->common_channels;
361 362

  // check uplink failure
363 364
  if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 0) &&
      (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
365 366 367
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 1)
      LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti,
            UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);
368 369
    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;
370

371
      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
372 373
      nfapi_dl_config_request_pdu_t *dl_config_pdu                    = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu];
      memset((void *) dl_config_pdu, 0,sizeof(nfapi_dl_config_request_pdu_t));
374
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
375 376
      dl_config_pdu->pdu_size                                         = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
377
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
378 379 380
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level     = get_aggregation(get_bw_index(module_idP, CC_id),
											UE_list->UE_sched_ctrl[UE_id].
											dl_cqi[CC_id], format1A);
381
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                  = rnti;
382 383
      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
384

385 386 387
      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);
388
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
389 390
      DL_req[CC_id].dl_config_request_body.number_dci++;
      DL_req[CC_id].dl_config_request_body.number_pdu++;
391
      DL_req[CC_id].dl_config_request_body.tl.tag                      = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
392
      LOG_D(MAC,
393 394 395 396 397 398
	    "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",
	    UE_id, rnti,
	    UE_list->UE_sched_ctrl[UE_id].ul_failure_timer,
	    dl_config_pdu->dci_dl_pdu.
	    dci_dl_pdu_rel8.resource_block_coding);
    } else {		// ra_pdcch_sent==1
Wang Tsu-Han's avatar
Wang Tsu-Han committed
399
      LOG_D(MAC,
400 401 402
	    "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);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
403
      if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0;	// resend every 8 frames
404
    }
405

406 407
    UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++;
    // check threshold
Wang Tsu-Han's avatar
Wang Tsu-Han committed
408 409
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) {
      // note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311)
410
      // inform RRC of failure and clear timer
411 412 413 414 415 416
      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;
417 418 419 420 421 422 423

      //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
      if (rrc_agent_registered[module_idP]) {
        LOG_W(MAC, "notify flexran Agent of UE state change\n");
        agent_rrc_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
            rnti, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
      }
424
    }
425
  }				// ul_failure_timer>0
426
}
427

428 429 430
void
clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP,
			frame_t frameP, sub_frame_t subframeP)
431
{
432 433
  nfapi_dl_config_request_t      *DL_req = &eNB->DL_req[0];
  nfapi_ul_config_request_t      *UL_req = &eNB->UL_req[0];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
434
  nfapi_hi_dci0_request_t   *HI_DCI0_req = &eNB->HI_DCI0_req[CC_idP][subframeP];
435
  nfapi_tx_request_t             *TX_req = &eNB->TX_req[0];
436

437
  eNB->pdu_index[CC_idP] = 0;
438

439
  if (nfapi_mode==0 || nfapi_mode == 1) { // monolithic or PNF
440

441 442 443 444 445
    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;
446

Wang Tsu-Han's avatar
Wang Tsu-Han committed
447 448
    HI_DCI0_req->hi_dci0_request_body.sfnsf                                   = subframeP + (frameP<<4);
    HI_DCI0_req->hi_dci0_request_body.number_of_dci                           = 0;
449 450


451 452 453
    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
454

455
    TX_req[CC_idP].tx_request_body.number_of_pdus                 = 0;
456

457
  }
458 459
}

460 461
void
copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
462
{
463
  int CC_id;
464
  eNB_MAC_INST *mac = RC.mac[module_idP];
465

466
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
467

468 469 470
    nfapi_ul_config_request_t *ul_req_tmp             = &mac->UL_req_tmp[CC_id][subframeP];
    nfapi_ul_config_request_t *ul_req                 = &mac->UL_req[CC_id];
    nfapi_ul_config_request_pdu_t *ul_req_pdu         = ul_req->ul_config_request_body.ul_config_pdu_list;
471

472
    *ul_req = *ul_req_tmp;
473

474 475 476 477
    // Restore the pointer
    ul_req->ul_config_request_body.ul_config_pdu_list = ul_req_pdu;
    ul_req->sfn_sf                                    = (frameP<<4) + subframeP;
    ul_req_tmp->ul_config_request_body.number_of_pdus = 0;
478

479
    if (ul_req->ul_config_request_body.number_of_pdus>0)
480 481 482
      {
        LOG_D(PHY, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
      }
483

484 485 486
    memcpy((void*)ul_req->ul_config_request_body.ul_config_pdu_list,
	   (void*)ul_req_tmp->ul_config_request_body.ul_config_pdu_list,
	   ul_req->ul_config_request_body.number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t));
487
  }
488 489
}

490 491 492
void
eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
			  sub_frame_t subframeP)
493
{
494

495
  int               mbsfn_status[MAX_NUM_CCs];
496
  protocol_ctxt_t   ctxt;
497

498
  int               CC_id, i = -1;
499 500
  UE_list_t         *UE_list = &RC.mac[module_idP]->UE_list;
  rnti_t            rnti;
501

502
  COMMON_channels_t *cc      = RC.mac[module_idP]->common_channels;
503

504
  start_meas(&RC.mac[module_idP]->eNB_scheduler);
505 506 507
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
    (VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,
     VCD_FUNCTION_IN);
508

509 510
  RC.mac[module_idP]->frame    = frameP;
  RC.mac[module_idP]->subframe = subframeP;
511

512 513
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    mbsfn_status[CC_id] = 0;
514 515

    // clear vrb_maps
516 517
    memset(cc[CC_id].vrb_map, 0, 100);
    memset(cc[CC_id].vrb_map_UL, 0, 100);
518

519

520
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
521
    cc[CC_id].mcch_active        = 0;
522
#endif
523

524
    clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, subframeP);
525 526
  }

Raymond Knopp's avatar
 
Raymond Knopp committed
527
  // refresh UE list based on UEs dropped by PHY in previous subframe
528 529 530 531 532 533 534 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 563 564 565 566
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
    if (UE_list->active[i]) {
      rnti = UE_RNTI(module_idP, i);
      CC_id = UE_PCCID(module_idP, i);
      
      if (((frameP&127) == 0) && (subframeP == 0)) {
	LOG_I(MAC,
	      "UE  rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n",
	      rnti,
	      UE_list->UE_sched_ctrl[i].ul_out_of_sync ==
	      0 ? "in synch" : "out of sync",
	      UE_list->UE_template[CC_id][i].phr_info,
	      UE_list->UE_sched_ctrl[i].dl_cqi[CC_id],
	      (UE_list->UE_sched_ctrl[i].pusch_snr[CC_id] - 128) / 2,
	      (UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id] - 128) / 2);
      }
      
      RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP * 10) +
						    subframeP] = -63;
      if (i == UE_list->head)
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME
	  (VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,
	   RC.eNB[module_idP][CC_id]->
	   pusch_stats_bsr[i][(frameP * 10) + subframeP]);
      // increment this, it is cleared when we receive an sdu
      RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++;
      
      RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++;
      LOG_D(MAC, "UE %d/%x : ul_inactivity %d, cqi_req %d\n", i, rnti,
	    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].
	    ul_inactivity_timer,
	    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer);
      check_ul_failure(module_idP, CC_id, i, frameP, subframeP);
      
      if (RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer > 0) {
	RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer++;
	if(RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer >=
	   RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer_thres) {
	  RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
567 568 569 570 571 572 573 574 575
          //clear reestablish_rnti_map
          if(RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer_thres >20){
	    for (int ue_id_l = 0; ue_id_l < MAX_MOBILES_PER_ENB; ue_id_l++) {
	      if (reestablish_rnti_map[ue_id_l][0] == rnti) {
	        // clear currentC-RNTI from map
	        reestablish_rnti_map[ue_id_l][0] = 0;
	        reestablish_rnti_map[ue_id_l][1] = 0;
	        break;
	      }
576
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
577 578 579 580 581

            PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rnti, 0, 0,module_idP);
            rrc_rlc_remove_ue(&ctxt);
            pdcp_remove_UE(&ctxt);
          }
582 583 584 585
	  // Note: This should not be done in the MAC!
	  for (int ii=0; ii<MAX_MOBILES_PER_ENB; ii++) {
	    LTE_eNB_ULSCH_t *ulsch = RC.eNB[module_idP][CC_id]->ulsch[ii];
	    if((ulsch != NULL) && (ulsch->rnti == rnti)){
586
              void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
587 588 589
	      LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti);
	      clean_eNb_ulsch(ulsch);
	    }
590
	  }
591 592 593
	  for (int ii=0; ii<MAX_MOBILES_PER_ENB; ii++) {
	    LTE_eNB_DLSCH_t *dlsch = RC.eNB[module_idP][CC_id]->dlsch[ii][0];
	    if((dlsch != NULL) && (dlsch->rnti == rnti)){
594
              void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
595 596 597
	      LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti);
	      clean_eNb_dlsch(dlsch);
	    }
598
	  }
599 600 601 602 603 604 605 606 607 608 609 610 611
	  
	  for(int j = 0; j < 10; j++){
	    nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
	    ul_req_tmp = &RC.mac[module_idP]->UL_req_tmp[CC_id][j].ul_config_request_body;
	    if(ul_req_tmp){
	      int pdu_number = ul_req_tmp->number_of_pdus;
	      for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){
		if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){
		  LOG_I(MAC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number);
		  if(pdu_index < pdu_number -1){
		    memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
		  }
		  ul_req_tmp->number_of_pdus--;
612 613 614 615 616
		}
	      }
	    }
	  }
	rrc_mac_remove_ue(module_idP,rnti);
617
	}
618
      }
619
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
620
  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
621 622

#if (!defined(PRE_SCD_THREAD))
623 624 625
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES,
				 NOT_A_RNTI, frameP, subframeP,
				 module_idP);
626
  pdcp_run(&ctxt);
627

Raymond Knopp's avatar
Raymond Knopp committed
628
  rrc_rx_tx(&ctxt, CC_id);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
629
#endif
630

631
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
632

633 634
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    if (cc[CC_id].MBMS_flag > 0) {
635
      start_meas(&RC.mac[module_idP]->schedule_mch);
636
      mbsfn_status[CC_id] = schedule_MBMS(module_idP, CC_id, frameP, subframeP);
637
      stop_meas(&RC.mac[module_idP]->schedule_mch);
Raymond Knopp's avatar
 
Raymond Knopp committed
638
    }
639
  }
640

641
#endif
642

Wang Tsu-Han's avatar
Wang Tsu-Han committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
  static int debug_flag=0;
  void (*schedule_ulsch_p)(module_id_t module_idP, frame_t frameP, sub_frame_t subframe)=NULL;
  void (*schedule_ue_spec_p)(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int *mbsfn_flag)=NULL;
  if(RC.mac[module_idP]->scheduler_mode == SCHED_MODE_DEFAULT){
    schedule_ulsch_p = schedule_ulsch;
    schedule_ue_spec_p = schedule_dlsch;
  }else if(RC.mac[module_idP]->scheduler_mode == SCHED_MODE_FAIR_RR){
    memset(dlsch_ue_select, 0, sizeof(dlsch_ue_select));
    schedule_ulsch_p = schedule_ulsch_fairRR;
    schedule_ue_spec_p = schedule_ue_spec_fairRR;
  }
  if(debug_flag==0){
    LOG_E(MAC,"SCHED_MODE=%d\n",RC.mac[module_idP]->scheduler_mode);
    debug_flag=1;
  }

659
  // This schedules MIB
660

661
  if ((subframeP == 0) && (frameP & 3) == 0)
662
      schedule_mib(module_idP, frameP, subframeP);
663
  if (phy_test == 0){
664
    // This schedules SI for legacy LTE and eMTC starting in subframeP
665 666 667
    schedule_SI(module_idP, frameP, subframeP);
    // This schedules Paging in subframeP
    schedule_PCH(module_idP,frameP,subframeP);
668
    // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
669
    schedule_RA(module_idP, frameP, subframeP);
670
    // copy previously scheduled UL resources (ULSCH + HARQ)
671
    copy_ulreq(module_idP, frameP, subframeP);
672
    // This schedules SRS in subframeP
673
    schedule_SRS(module_idP, frameP, subframeP);
674
    // This schedules ULSCH in subframeP (dci0)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
675 676 677 678 679
    if (schedule_ulsch_p != NULL) {
       schedule_ulsch_p(module_idP, frameP, subframeP);
    } else {
       LOG_E(MAC," %s %d: schedule_ulsch_p is NULL, function not called\n",__FILE__,__LINE__); 
    }
680
    // This schedules UCI_SR in subframeP
681
    schedule_SR(module_idP, frameP, subframeP);
682 683 684
    // This schedules UCI_CSI in subframeP
    schedule_CSI(module_idP, frameP, subframeP);
    // This schedules DLSCH in subframeP
Wang Tsu-Han's avatar
Wang Tsu-Han committed
685 686 687 688 689 690
    if (schedule_ue_spec_p != NULL) {
       schedule_ue_spec_p(module_idP, frameP, subframeP, mbsfn_status);
    } else {
       LOG_E(MAC," %s %d: schedule_ue_spec_p is NULL, function not called\n",__FILE__,__LINE__); 
    }

691
  }
692
  else{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
693
    schedule_ulsch_phy_test(module_idP,frameP,subframeP);
694 695
    schedule_ue_spec_phy_test(module_idP,frameP,subframeP,mbsfn_status);
  }
696

697 698
  if (RC.flexran[module_idP]->enabled)
    flexran_agent_send_update_stats(module_idP);
699
  
700
  // Allocate CCEs for good after scheduling is done
Wang Tsu-Han's avatar
Wang Tsu-Han committed
701 702 703 704
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    if(cc[CC_id].tdd_Config == NULL || !(is_UL_sf(&cc[CC_id],subframeP)))
      allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2);
  }
705

706
  stop_meas(&RC.mac[module_idP]->eNB_scheduler);
707

708 709 710
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
      (VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,
      VCD_FUNCTION_OUT);
711
}