eNB_scheduler.c 34.3 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
#include "targets/RT/USER/lte-softmodem.h"
34 35
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
36

37
#include "LAYER2/MAC/mac_proto.h"
38 39
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
40 41 42
#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

54 55
/* for fair round robin SCHED */
#include "eNB_scheduler_fairRR.h"
56

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

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
  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;
82 83
  LTE_SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon;
  struct LTE_SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated;
84 85 86 87
  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 == LTE_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
  int                            CC_id, UE_id;
165
  struct LTE_CQI_ReportPeriodic  *cqi_ReportPeriodic;
166 167
  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
	if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) != NULL
188
	    && (cqi_ReportPeriodic->present != LTE_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 (LTE_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
  LTE_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
      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) {
272
	if (SRconfig->present == LTE_SchedulingRequestConfig_PR_setup) {
273 274 275 276 277 278 279 280 281 282 283 284 285
	  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 (LTE_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)) {
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;
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
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);
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
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];
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;
haswell's avatar
haswell committed
446
    DL_req[CC_idP].sfn_sf                                                     = subframeP + (frameP<<4);
447

448 449
    HI_DCI0_req->hi_dci0_request_body.sfnsf                                   = subframeP + (frameP<<4);
    HI_DCI0_req->hi_dci0_request_body.number_of_dci                           = 0;
450

451

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

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

458
  }
459 460
}

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

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

469 470 471
    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;
472

473
    *ul_req = *ul_req_tmp;
474

475 476 477 478
    // 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;
479

480
    if (ul_req->ul_config_request_body.number_of_pdus>0)
481 482 483
      {
        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);
      }
484

485 486 487
    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));
488
  }
489 490
}

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

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

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

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

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

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

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

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

520

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
528
  // refresh UE list based on UEs dropped by PHY in previous subframe
529 530 531 532 533 534 535 536 537 538 539 540 541
  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],
542 543
	      (5*UE_list->UE_sched_ctrl[i].pusch_snr[CC_id] - 640) / 10,
	      (5*UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id] - 640) / 10);
544
      }
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
      
      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;
568 569 570 571 572 573 574 575 576
          //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;
	      }
577
	    }
578

579 580 581 582
            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);
          }
583 584 585 586
	  // 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)){
587
              void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
588 589 590
	      LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti);
	      clean_eNb_ulsch(ulsch);
	    }
591
	  }
592 593 594
	  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)){
595
              void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
596 597 598
	      LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti);
	      clean_eNb_dlsch(dlsch);
	    }
599
	  }
600 601 602 603 604 605 606 607 608 609 610 611 612
	  
	  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--;
613 614 615 616 617
		}
	      }
	    }
	  }
	rrc_mac_remove_ue(module_idP,rnti);
618
	}
619
      }
620
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
621
  }
622

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

Raymond Knopp's avatar
Raymond Knopp committed
629
  rrc_rx_tx(&ctxt, CC_id);
630
#endif
631

632
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
633

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

642
#endif
643

644
  static int debug_flag=0;
645 646
  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;
647 648 649 650 651 652 653 654 655 656 657 658 659
  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;
  }

660
  // This schedules MIB
661
  if ((subframeP == 0) && (frameP & 3) == 0)
662
      schedule_mib(module_idP, frameP, subframeP);
663
  if (get_softmodem_params()->phy_test == 0){
664 665
    // This schedules SI for legacy LTE and eMTC starting in subframeP
    schedule_SI(module_idP, frameP, subframeP);
666 667
    // This schedules Paging in subframeP
    schedule_PCH(module_idP,frameP,subframeP);
668 669 670 671 672 673 674
    // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
    schedule_RA(module_idP, frameP, subframeP);
    // copy previously scheduled UL resources (ULSCH + HARQ)
    copy_ulreq(module_idP, frameP, subframeP);
    // This schedules SRS in subframeP
    schedule_SRS(module_idP, frameP, subframeP);
    // This schedules ULSCH in subframeP (dci0)
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 681 682 683
    // This schedules UCI_SR in subframeP
    schedule_SR(module_idP, frameP, subframeP);
    // This schedules UCI_CSI in subframeP
    schedule_CSI(module_idP, frameP, subframeP);
684 685 686
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
    // This schedules DLSCH in subframeP
    schedule_ue_spec_br(module_idP,frameP,subframeP);
687
#endif
688
    // This schedules DLSCH in subframeP
689 690 691 692 693
    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__); 
    }
694

695
  }
696
  else{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
697
    schedule_ulsch_phy_test(module_idP,frameP,subframeP);
698 699
    schedule_ue_spec_phy_test(module_idP,frameP,subframeP,mbsfn_status);
  }
700

701 702
  if (RC.flexran[module_idP]->enabled)
    flexran_agent_send_update_stats(module_idP);
703
  
704
  // Allocate CCEs for good after scheduling is done
705 706 707 708
  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);
  }
709

710 711 712
  if (mac_agent_registered[module_idP] && subframeP == 9) {
    flexran_agent_slice_update(module_idP);
  }
713

714
  stop_meas(&RC.mac[module_idP]->eNB_scheduler);
715

716 717 718
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
      (VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,
      VCD_FUNCTION_OUT);
719
}