eNB_scheduler.c 30 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
nikaeinn's avatar
nikaeinn committed
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"
gauthier's avatar
gauthier committed
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"
gauthier's avatar
gauthier committed
48

49
50
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
gauthier's avatar
gauthier committed
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
uint16_t pdcch_order_table[6] = {31,31,511,2047,2047,8191};

73

74
75
void schedule_SRS(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP)
{
76
77
78
  eNB_MAC_INST                   *eNB            = RC.mac[module_idP];
  UE_list_t                      *UE_list        = &eNB->UE_list;
  nfapi_ul_config_request_body_t *ul_req;
79
  int CC_id,UE_id;
80
81
82
83
84
85
  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;
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  // 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

  uint16_t srsPeriodicity,srsOffset;

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
    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;
      if (cc[CC_id].tdd_Config == NULL) { // FDD
	deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
	TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
      }
      else { // TDD
	deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
	TSFC      = deltaTSFCTabType2[srs_SubframeConfig][1];
      }
      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
      uint16_t tmp = (subframeP %  TSFC);

      if((1<<tmp) & deltaTSFC) {
	// This is an SRS subframe, loop over UEs
111
112
	for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
	  if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue;
113
	  ul_req        = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
114
115


116
117
118
          // 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;

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

121
122
123
124
125
126
	  if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) {
	    if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
	      get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, &srsPeriodicity, &srsOffset);
	      if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) {
		// Prorgram SRS
		ul_req->srs_present                                                 = 1;
127
		nfapi_ul_config_request_pdu_t* ul_config_pdu                        = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
128
129
130
		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));
131
132
		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);
133
134
135
136
137
		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;
138
139
		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;
140
141
142
		//		ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
		//		ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
		RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP<<4)+subframeP;
143
		RC.mac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
144
		ul_req->number_of_pdus++;
145
146
147
	      } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
	    } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
	  } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
148
149
150
151
152
153
154
	} // for (UE_id ...
      } // if((1<<tmp) & deltaTSFC)

    }// SRS config
  }
}

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

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

    cc = &eNB->common_channels[CC_id];
169
170
    for (UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
      if (UE_list->active[UE_id] != TRUE) continue;
171
172
173

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

Cedric Roux's avatar
Cedric Roux committed
174
175
176
      // 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;

177
178
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);

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

	  get_csi_params(cc,cqi_ReportPeriodic,&Npd,&N_OFFSET_CQI,&H);
185

186
187
188
	  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;
	    // Program CQI
189
	    nfapi_ul_config_request_pdu_t* ul_config_pdu                                     = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
190
191
192
	    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));
193
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
194
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
195
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
196
197
198
199
200
201
202
	    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  = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id],
															CC_id,
															cc,
															get_tmode(module_idP,CC_id,UE_id),
															cqi_ReportPeriodic);
	    ul_req->number_of_pdus++;
203
	    ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
204
205
206

#if defined(Rel10) || defined(Rel14)
	    // PUT rel10-13 UCI options here
207
#endif
208
209
210
211
212
	  }
	  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
213
	    nfapi_ul_config_request_pdu_t* ul_config_pdu                                     = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
214
215
216
	    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));
217
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
218
	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
219
	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
220
221
222
223
	    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++;
224
	    ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
225
226
227
228
229
230
231
232
	  }

	} // 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++) {
}

233
234
235
236
void schedule_SR(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
{
  eNB_MAC_INST                   *eNB        = RC.mac[module_idP];
  UE_list_t                      *UE_list    = &eNB->UE_list;
237
238
  nfapi_ul_config_request_t      *ul_req;
  nfapi_ul_config_request_body_t *ul_req_body;
239
240
  int                             CC_id;
  int                             UE_id;
241
  SchedulingRequestConfig_t      *SRconfig;
242
243
244
245
  int                             skip_ue;
  int                             is_harq;
  nfapi_ul_config_sr_information  sr;
  int                             i;
246

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

250
251
    for (UE_id = 0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
      if (RC.mac[module_idP]->UE_list.active[UE_id]!=TRUE) continue;
252

253
254
      ul_req        = &RC.mac[module_idP]->UL_req[CC_id];
      ul_req_body   = &ul_req->ul_config_request_body;
255

256
      //LOG_D(MAC, "UE active UE_id:%d ul_req_body->number_of_pdus:%d\n", UE_id, ul_req_body->number_of_pdus);
257

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

260
261
262
      // 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;

263
      if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) {
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
        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)
283
284
285

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

286
287
      skip_ue=0;
      is_harq = 0;
288
      // check that there is no existing UL grant for ULSCH which overrides the SR
289
290
291
292
293
294
      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)) {
295
296
297
298
            skip_ue=1;
            break;
        }
        /* if there is already an HARQ pdu, convert to SR_HARQ */
299
300
        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)) {
301
302
303
304
          is_harq = 1;
          break;
        }
      }
305
306

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

309
      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);
310
311
312
313

      // check Rel10 or Rel8 SR
#if defined(Rel10) || defined(Rel14)
      if ((UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) &&
314
          (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) {
315
316
        sr.sr_information_rel8.tl.tag = 0;
        sr.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
317
318
        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;
319
320

        LOG_D(MAC,"REL10 PUCCH INDEX P1:%d\n", sr.sr_information_rel10.pucch_index_p1);
321
      } else
322
#endif
323
      {
324
        sr.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
325
        sr.sr_information_rel8.pucch_index = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
326
327
328
        sr.sr_information_rel10.tl.tag = 0;

        LOG_D(MAC,"REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index);
329
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
        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++;
345
      } /* if (is_harq) */
346
347
      ul_req_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;

348
349
350
351
    } // 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++)
}

352
void check_ul_failure(module_id_t module_idP,int CC_id,int UE_id,
353
354
		      frame_t frameP, sub_frame_t subframeP)
{
355
  UE_list_t                           *UE_list      = &RC.mac[module_idP]->UE_list;
356
  nfapi_dl_config_request_t           *DL_req       = &RC.mac[module_idP]->DL_req[0];
357
358
359
360
361
362
  uint16_t                            rnti          = UE_RNTI(module_idP,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)) {
363
    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);
364
365
    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;
366

367
      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
368
      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];
369
      memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
370
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
371
      dl_config_pdu->pdu_size                                         = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
372
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
373
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
Cedric Roux's avatar
Cedric Roux committed
374
      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);
375
376
377
      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
378

379
380
381
      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];
382
      DL_req[CC_id].dl_config_request_body.number_dci++;
383
384
      LOG_E(MAC, "%s() number_dci:%u\n", __FUNCTION__, DL_req[CC_id].dl_config_request_body.number_dci);

385
      DL_req[CC_id].dl_config_request_body.number_pdu++;
386
      DL_req[CC_id].dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
387
     
388
      LOG_I(MAC,"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);
389
390
    }
    else { // ra_pdcch_sent==1
391
      LOG_I(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);
392
      if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0)
393
	UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent=0; // resend every 4 frames
394
    }
395

396
397
398
399
    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
400
      LOG_I(MAC,"UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti);
401
402
403
404
405
406
      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

407
}
408

409
410
extern uint8_t nfapi_mode;

411
412
void clear_nfapi_information(eNB_MAC_INST *eNB,int CC_idP,frame_t frameP,sub_frame_t subframeP)
{
413
414
415
416
  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];
417

418
  eNB->pdu_index[CC_idP]                                     = 0;
419

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  if (nfapi_mode==0 || nfapi_mode == 1)   // monolithic or PNF
  {
    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<<4);
    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;

    LOG_D(MAC,"%s() SFN_SF:%d%d ZERO PDUs of TX_req:(SFN_SF:%d):%d UL_req:(SFN_SF:%d):%d HI_DCI0_req:(SFN_SF:%d):dci:%d hi:%d DL:(SFN_SF:%d):dci:%d DL:pdu:%d\n", 
        __FUNCTION__,
        frameP, subframeP,
        NFAPI_SFNSF2DEC(TX_req[CC_idP].sfn_sf),
        TX_req[CC_idP].tx_request_body.number_of_pdus,
        NFAPI_SFNSF2DEC(UL_req[CC_idP].sfn_sf),
        UL_req[CC_idP].ul_config_request_body.number_of_pdus,
        NFAPI_SFNSF2DEC(HI_DCI0_req[CC_idP].sfn_sf),
        HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci,
        HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_hi,
        NFAPI_SFNSF2DEC(DL_req[CC_idP].sfn_sf),
        DL_req[CC_idP].dl_config_request_body.number_dci,
        DL_req[CC_idP].dl_config_request_body.number_pdu);
  }
453
454
}

455
456
void copy_ulreq(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP)
{
457
  int CC_id;
David Price's avatar
David Price committed
458
  eNB_MAC_INST *eNB = RC.mac[module_idP];
459
460
461

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

David Price's avatar
David Price committed
462
463
464
465
466
    nfapi_ul_config_request_t *ul_req_tmp = &eNB->UL_req_tmp[CC_id][subframeP];
    nfapi_ul_config_request_t *ul_req     = &eNB->UL_req[CC_id];
    nfapi_ul_config_request_pdu_t *ul_req_pdu = ul_req->ul_config_request_body.ul_config_pdu_list;

    *ul_req = *ul_req_tmp;
467

David Price's avatar
David Price committed
468
469
    // Restore the pointer
    ul_req->ul_config_request_body.ul_config_pdu_list = ul_req_pdu;
470

David Price's avatar
David Price committed
471
472
473
474
475
    ul_req->sfn_sf   = (frameP<<4) + subframeP;

    ul_req_tmp->ul_config_request_body.number_of_pdus = 0;

    if (ul_req->ul_config_request_body.number_of_pdus>0)
476
    {
David Price's avatar
David Price committed
477
      LOG_E(PHY, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
478
    }
479

David Price's avatar
David Price committed
480
481
482
    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));
483
  }
484
485
}

486
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
487
{
488

knopp's avatar
   
knopp committed
489
  int mbsfn_status[MAX_NUM_CCs];
490
  protocol_ctxt_t   ctxt;
491

492
  int CC_id,i; //,next_i;
493
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
494
  rnti_t rnti;
495

496
  COMMON_channels_t         *cc             = RC.mac[module_idP]->common_channels;
497

498
#if defined(FLEXRAN_AGENT_SB_IF)
499
  Protocol__FlexranMessage *msg;
500
#endif
501

502

503
  start_meas(&RC.mac[module_idP]->eNB_scheduler);
gauthier's avatar
gauthier committed
504
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
505

506
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
   
knopp committed
507
    mbsfn_status[CC_id]=0;
508
509

    // clear vrb_maps
knopp's avatar
knopp committed
510
    memset(cc[CC_id].vrb_map,0,100);
511
    memset(cc[CC_id].vrb_map_UL,0,100);
512

513

Cedric Roux's avatar
Cedric Roux committed
514
#if defined(Rel10) || defined(Rel14)
knopp's avatar
knopp committed
515
    cc[CC_id].mcch_active =0;
516
#endif
517
518
    RC.mac[module_idP]->frame    = frameP;
    RC.mac[module_idP]->subframe = subframeP;
519
520
  }

knopp's avatar
   
knopp committed
521
  // refresh UE list based on UEs dropped by PHY in previous subframe
522
523
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] != TRUE) continue;
524

525
526
527
    rnti         = UE_RNTI(module_idP, i);
    CC_id        = UE_PCCID(module_idP, i);

528
    if ((frameP==0)&&(subframeP==0)) {
knopp's avatar
knopp committed
529
      LOG_I(MAC,"UE  rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", rnti,
530
531
            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,
knopp's avatar
knopp committed
532
533
            UE_list->UE_sched_ctrl[i].dl_cqi[CC_id],
	    (UE_list->UE_sched_ctrl[i].pusch_snr[CC_id]-128)/2,
534
	    (UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id]-128)/2);
535
    }
536

537
    RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63;
538
    if (i==UE_list->head)
539
      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]);
540
    // increment this, it is cleared when we receive an sdu
541
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ul_inactivity_timer++;
542

543
    RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer++;
544
    LOG_D(MAC,"UE %d/%x : ul_inactivity %d, cqi_req %d\n",i,rnti,
knopp's avatar
knopp committed
545
546
	  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);
547
548
    check_ul_failure(module_idP,CC_id,i,frameP,subframeP);

knopp's avatar
   
knopp committed
549
  }
550

551
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
552
  pdcp_run(&ctxt);
553

554
555
  rrc_rx_tx(&ctxt,
            0, // eNB index, unused in eNB
556
            CC_id);
557

Cedric Roux's avatar
Cedric Roux committed
558
#if defined(Rel10) || defined(Rel14)
559
560

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
knopp committed
561
    if (cc[CC_id].MBMS_flag >0) {
562
      start_meas(&RC.mac[module_idP]->schedule_mch);
563
      mbsfn_status[CC_id] = schedule_MBMS(module_idP,CC_id,frameP,subframeP);
564
      stop_meas(&RC.mac[module_idP]->schedule_mch);
knopp's avatar
   
knopp committed
565
    }
566
  }
567

568
#endif
569

570
  // This schedules MIB
571
572
  //if ((subframeP==0) && (frameP&3) == 0) schedule_mib(module_idP,frameP,subframeP);
  if (subframeP==0) schedule_mib(module_idP,frameP,subframeP);
573
  // This schedules SI for legacy LTE and eMTC starting in subframeP
574
  schedule_SI(module_idP,frameP,subframeP);
575
  // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
576
  schedule_RA(module_idP,frameP,subframeP);
577
578
579
580
581
  // 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)
582
  schedule_ulsch(module_idP,frameP,subframeP);
583
  // This schedules UCI_SR in subframeP
David Price's avatar
David Price committed
584
  //schedule_SR(module_idP,frameP,subframeP);
585
586
  // This schedules UCI_CSI in subframeP
  schedule_CSI(module_idP, frameP, subframeP);
587

588
  // This schedules DLSCH in subframeP
589
590
  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);

591
  // Allocate CCEs for good after scheduling is done
592

593
594
  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) allocate_CCEs(module_idP,CC_id,subframeP,0);
  
595

596
  stop_meas(&RC.mac[module_idP]->eNB_scheduler);
597

gauthier's avatar
gauthier committed
598
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);
599
}