eNB_scheduler.c 52.9 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
Cedric Roux's avatar
Cedric Roux committed
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
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
#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
#include "common/utils/LOG/log.h"
frtabu's avatar
frtabu committed
39
#include "nfapi/oai_integration/vendor_ext.h"
40
#include "common/utils/LOG/vcd_signal_dumper.h"
41
42
43
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
gauthier's avatar
gauthier committed
44

45
#include "RRC/LTE/rrc_extern.h"
46
#include "RRC/NR/nr_rrc_extern.h"
47
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
gauthier's avatar
gauthier committed
48

49
50
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
51

52
//Agent-related headers
53
54
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
55

56
57
58
/* for fair round robin SCHED */
#include "eNB_scheduler_fairRR.h"

59
#include "intertask_interface.h"
60

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
74
75
76
77
78
//-----------------------------------------------------------------------------
/*
 * Schedule periodic SRS
 */
void schedule_SRS(module_id_t module_idP,
                  frame_t frameP,
                  sub_frame_t subframeP)
//-----------------------------------------------------------------------------
79
{
80
81
82
83
84
85
86
  int CC_id = 0;
  int UE_id = -1;
  uint8_t TSFC = 0;
  uint8_t srs_SubframeConfig = 0;
  uint16_t srsPeriodicity = 0;
  uint16_t srsOffset = 0;
  uint16_t deltaTSFC = 0;  // bitmap
87
  // table for TSFC (Period) and deltaSFC (offset)
88
89
90
  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
  eNB_MAC_INST *eNB = RC.mac[module_idP];
91
  UE_info_t *UE_info = &eNB->UE_info;
92
  nfapi_ul_config_request_body_t *ul_req = NULL;
93
  UE_sched_ctrl_t *UE_scheduling_control = NULL;
94
95
96
97
  COMMON_channels_t *cc = eNB->common_channels;
  LTE_SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon = NULL;
  struct LTE_SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated = NULL;

98
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
99
100
101
    soundingRS_UL_ConfigCommon = &(cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon);

    /* Check if SRS is enabled in this frame/subframe */
102
103
    if (soundingRS_UL_ConfigCommon) {
      srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
104
105
106
107
108
109
110

      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];
111
      }
112
113

      /* Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC) */
114
      uint16_t tmp = (subframeP % TSFC);
115

116
      if ((1 << tmp) & deltaTSFC) {
117
118
        /* This is an SRS subframe, loop over UEs */
        for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
119
          if (!UE_info->active[UE_id]) {
120
121
122
123
124
125
126
127
            continue;
          }

          /* 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;
          }

128
          if(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) {
129
130
131
132
            LOG_E(MAC,"physicalConfigDedicated is null for UE %d\n",UE_id);
            printf("physicalConfigDedicated is null for UE %d\n",UE_id);
            return;
          }
133
134

          /* CDRX condition on Active Time and SRS type-0 report (36.321 5.7) */
135
          UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
136
137
138
139
140
141
142
143
144
145
146

          /* Test if Active Time not running since 6+ subframes */
          if (UE_scheduling_control->cdrx_configured == TRUE && UE_scheduling_control->in_active_time == FALSE) {
            /*
             * TODO: 6+ subframes condition not checked here
             */
            continue;
          }

          ul_req = &(eNB->UL_req[CC_id].ul_config_request_body);

147
          if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
            if (soundingRS_UL_ConfigDedicated->present == LTE_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) {
                // Program SRS
                ul_req->srs_present = 1;
                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);
163
                ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
164
165
166
167
168
169
170
171
172
173
174
                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;
                eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
                eNB->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
                ul_req->number_of_pdus++;
              } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
            } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
175
          } // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
176
177
178
179
        } // end for loop on UE_id
      } // if((1<<tmp) & deltaTSFC)
    } // SRS config not NULL
  } // end for loop on CC_id
180
181
}

182
183
184
185
186
187
188
189
//-----------------------------------------------------------------------------
/*
* Schedule the CSI (CQI/PMI/RI/PTI/CRI) periodic reception
*/
void schedule_CSI(module_id_t module_idP,
                  frame_t frameP,
                  sub_frame_t subframeP)
//-----------------------------------------------------------------------------
190
{
191
192
193
194
195
196
  int                            CC_id = 0;
  int                            UE_id = 0;
  int                            H = 0;
  uint16_t                       Npd = 0;
  uint16_t                       N_OFFSET_CQI = 0;
  struct LTE_CQI_ReportPeriodic  *cqi_ReportPeriodic = NULL;
197
  eNB_MAC_INST                   *eNB = RC.mac[module_idP];
198
  UE_info_t                      *UE_info = &eNB->UE_info;
199
200
  COMMON_channels_t              *cc = NULL;
  nfapi_ul_config_request_body_t *ul_req = NULL;
201
  UE_sched_ctrl_t *UE_scheduling_control = NULL;
202
203
204

  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    cc = &eNB->common_channels[CC_id];
205

knopp's avatar
knopp committed
206
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
207
      if (UE_info->active[UE_id] == FALSE) {
208
209
210
211
212
213
214
215
        continue;
      }

      /* Drop the allocation if the UE hasn't sent RRCConnectionSetupComplete yet */
      if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) {
        continue;
      }

216
      AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
217
218
219
220
221
222
223
                  "physicalConfigDedicated is null for UE %d\n",
                  UE_id);
      /*
      * CDRX condition on Active Time and CSI report on PUCCH (36.321 5.7).
      * Here we consider classic periodic reports on PUCCH without PUSCH simultaneous transmission condition.
      * TODO: add the handling or test on simultaneous PUCCH/PUSCH transmission
      */
224
      UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

      if (UE_scheduling_control->cdrx_configured == TRUE) {
        /* Test if CQI masking activated */
        if (UE_scheduling_control->cqi_mask_boolean == TRUE) {
          // CQI masking => test if onDurationTime not running since 6+ subframe
          if (UE_scheduling_control->on_duration_timer == 0) {
            /*
             * TODO: 6+ subframes condition not checked here
             */
            continue;
          }
        } else { // No CQI masking => test if Active Time not running since 6+ subframe
          if (UE_scheduling_control->in_active_time == FALSE) {
            /*
             * TODO: 6+ subframes condition not checked here
             */
            continue;
          }
        }
      }

      ul_req = &(eNB->UL_req[CC_id].ul_config_request_body);

248
249
      if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) {
        cqi_ReportPeriodic = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic;
250
251
252
253
254
255
256
257
258
259
260
261
262
263

        if (cqi_ReportPeriodic != NULL) {
          /* Rel8 Periodic CSI (CQI/PMI/RI) reporting */
          if (cqi_ReportPeriodic->present != LTE_CQI_ReportPeriodic_PR_release) {
            get_csi_params(cc, cqi_ReportPeriodic, &Npd, &N_OFFSET_CQI, &H);

            if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) {  // CQI periodic opportunity
              UE_scheduling_control->feedback_cnt[CC_id] = (((frameP * 10) + subframeP) / Npd) % H;
              // Program CQI
              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;
264
              ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_info->UE_template[CC_id][UE_id].rnti;
265
266
              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;
267
              ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = get_rel8_dl_cqi_pmi_size(&UE_info->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id),
268
                  cqi_ReportPeriodic);
269
270
271
272
273
274
275
276
277
278
279
280
              ul_req->number_of_pdus++;
              ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
              // PUT rel10-13 UCI options here
            } else if (cqi_ReportPeriodic->choice.setup.ri_ConfigIndex != NULL) {
              if ((((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;
281
                ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_info->UE_template[CC_id][UE_id].rnti;
282
283
284
285
286
287
288
289
290
291
292
                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 CSI Periodic is not release state
        } // if (cqi_ReportPeriodic != NULL)
      } // if cqi_ReportConfig != NULL
293
    } // for (UE_id=UE_info->head; UE_id>=0; UE_id=UE_info->next[UE_id]) {
294
  } // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
295
296
}

297
298
299
300
//-----------------------------------------------------------------------------
/*
* Schedule a possible Scheduling Request reception
*/
301
void
302
303
304
305
schedule_SR (module_id_t module_idP,
             frame_t frameP,
             sub_frame_t subframeP)
//-----------------------------------------------------------------------------
306
{
307
308
309
310
  int skip_ue = 0;
  int is_harq = 0;
  int pdu_list_index = 0;
  eNB_MAC_INST *eNB = RC.mac[module_idP];
311
  UE_info_t *UE_info = &eNB->UE_info;
312
313
314
  nfapi_ul_config_request_t      *ul_req = NULL;
  nfapi_ul_config_request_body_t *ul_req_body = NULL;
  LTE_SchedulingRequestConfig_t  *SRconfig = NULL;
315
316
  nfapi_ul_config_sr_information sr;

317
318
  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
319

320
    for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
321
      if (!UE_info->active[UE_id]) {
322
323
        continue;
      }
324

325
      if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue;
326

327
      if ((SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) {
328
329
330
331
332
333
334
335
336
337
338
        if (SRconfig->present == LTE_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;
339
340
          } else if (SRconfig->choice.setup.sr_ConfigIndex <= 156) { // 2ms SR period
            if ((subframeP % 2) != (SRconfig->choice.setup.sr_ConfigIndex - 155)) continue;
341
342
          }
        }  // SRconfig->present == SchedulingRequestConfig_PR_setup)
343
      }  // SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL)
344

345
346
347
      /* If we get here there is some PUCCH1 reception to schedule for SR */
      ul_req = &(eNB->UL_req[CC_id]);
      ul_req_body = &(ul_req->ul_config_request_body);
348
349
      skip_ue = 0;
      is_harq = 0;
350
351
352
353
354
355
356
357
      pdu_list_index = 0;

      /* Check that there is no existing UL grant for ULSCH which overrides the SR */
      for (int 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)) &&
358
            (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) {
359
360
361
362
363
364
          skip_ue = 1;
          pdu_list_index = i;
          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) &&
365
                 (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) {
366
367
368
369
          is_harq = 1;
          pdu_list_index = i;
          break;
        }
370
      }
371

372
      /* Drop the allocation because ULSCH will handle it with BSR */
373
      if (skip_ue == 1) continue;
374

375
376
377
378
      LOG_D(MAC, "Frame %d, Subframe %d : Scheduling SR for UE %d/%x is_harq:%d \n",
            frameP,
            subframeP,
            UE_id,
379
            UE_info->UE_template[CC_id][UE_id].rnti,
380
            is_harq);
381

382
      /* Check Rel10 or Rel8 SR */
383
384
385
      if ((UE_info-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) &&
          (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) &&
          (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) {
386
387
        sr.sr_information_rel10.tl.tag                    = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
        sr.sr_information_rel10.number_of_pucch_resources = 1;
388
        sr.sr_information_rel10.pucch_index_p1            = *UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
389
        LOG_D(MAC, "REL10 PUCCH INDEX P1:%d \n", sr.sr_information_rel10.pucch_index_p1);
390
      } else {
391
        sr.sr_information_rel8.tl.tag      = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
392
        sr.sr_information_rel8.pucch_index = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
393
        LOG_D(MAC, "REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index);
394
      }
395

396
      /* If there is already an HARQ pdu, convert to SR_HARQ */
397
      if (is_harq) {
398
399
400
401
        nfapi_ul_config_harq_information harq                                            = ul_req_body->ul_config_pdu_list[pdu_list_index].uci_harq_pdu.harq_information;
        ul_req_body->ul_config_pdu_list[pdu_list_index].pdu_type                         = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
        ul_req_body->ul_config_pdu_list[pdu_list_index].uci_sr_harq_pdu.sr_information   = sr;
        ul_req_body->ul_config_pdu_list[pdu_list_index].uci_sr_harq_pdu.harq_information = harq;
402
      } else {
403
404
        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;
405
        ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti    = UE_info->UE_template[CC_id][UE_id].rnti;
406
407
408
409
410
411
412
413
414
        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 (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++)
  }  // for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
415
416
}

417
418
void
check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
419
                 frame_t frameP, sub_frame_t subframeP) {
420
  UE_info_t                 *UE_info = &RC.mac[module_idP]->UE_info;
421
422
423
424
425
  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;

  // check uplink failure
426
427
428
  if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) &&
      (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) {
    if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 1)
429
      LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti,
430
            UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
431

432
433
    if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) {
      UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1;
434
435
436
437
438
439
440
441
      // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
      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));
      dl_config_pdu->pdu_type                                         = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
      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;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format            = NFAPI_DL_DCI_FORMAT_1A;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level     = get_aggregation(get_bw_index(module_idP, CC_id),
442
          UE_info->UE_sched_ctrl[UE_id].
443
          dl_cqi[CC_id], format1A);
444
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                  = rnti;
445
446
      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
447
      AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >= 0) && (cc[CC_id].mib->message.dl_Bandwidth < 6),
448
449
                  "illegal dl_Bandwidth %d\n",
                  (int) cc[CC_id].mib->message.dl_Bandwidth);
450
451
452
453
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
      DL_req[CC_id].dl_config_request_body.number_dci++;
      DL_req[CC_id].dl_config_request_body.number_pdu++;
      DL_req[CC_id].dl_config_request_body.tl.tag                      = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
454
      DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
455
      LOG_D(MAC,
456
457
            "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",
            UE_id, rnti,
458
            UE_info->UE_sched_ctrl[UE_id].ul_failure_timer,
459
460
461
            dl_config_pdu->dci_dl_pdu.
            dci_dl_pdu_rel8.resource_block_coding);
    } else {    // ra_pdcch_sent==1
462
      LOG_D(MAC,
463
464
            "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",
            UE_id, rnti,
465
            UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
466

467
      if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0;  // resend every 8 frames
468
    }
469

470
    UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++;
471

472
    // check threshold
473
    if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) {
474
      // note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311)
475
      if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
476
        MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
477
478
479
480
481
482
483
484
        F1AP_UE_CONTEXT_RELEASE_REQ(m).rnti = rnti;
        F1AP_UE_CONTEXT_RELEASE_REQ(m).cause = F1AP_CAUSE_RADIO_NETWORK;
        F1AP_UE_CONTEXT_RELEASE_REQ(m).cause_value = 1; // 1 = F1AP_CauseRadioNetwork_rl_failure
        F1AP_UE_CONTEXT_RELEASE_REQ(m).rrc_container = NULL;
        F1AP_UE_CONTEXT_RELEASE_REQ(m).rrc_container_length = 0;
        itti_send_msg_to_task(TASK_DU_F1, module_idP, m);
      } else {
        // inform RRC of failure and clear timer
485
486
487
488
489
490
491
492
        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);
493
      }
frtabu's avatar
frtabu committed
494

495
496
      UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
      UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync   = 1;
497
    }
498
  }       // ul_failure_timer>0
499

500
  UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer++;
501

502
  if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) {
503
504
    LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti);
    mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti);
505
    UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer  = 0;
506
  }// time > 60s
507
}
508

509
void
510
511
clear_nfapi_information(eNB_MAC_INST *eNB, int CC_idP,
                        frame_t frameP, sub_frame_t subframeP) {
512
513
  nfapi_dl_config_request_t      *DL_req = &eNB->DL_req[0];
  nfapi_ul_config_request_t      *UL_req = &eNB->UL_req[0];
514
  nfapi_hi_dci0_request_t   *HI_DCI0_req = &eNB->HI_DCI0_req[CC_idP][subframeP];
515
516
  nfapi_tx_request_t             *TX_req = &eNB->TX_req[0];
  eNB->pdu_index[CC_idP] = 0;
517

frtabu's avatar
frtabu committed
518
  if (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MONOLITHIC) { // monolithic or PNF
519
520
521
522
523
    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
524
    DL_req[CC_idP].sfn_sf                                                     = subframeP + (frameP<<4);
525
526
    HI_DCI0_req->hi_dci0_request_body.sfnsf                                   = subframeP + (frameP<<4);
    HI_DCI0_req->hi_dci0_request_body.number_of_dci                           = 0;
527
528
529
530
531
    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;
  }
532
533
}

534
void
535
copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
536
537
  int CC_id;
  eNB_MAC_INST *mac = RC.mac[module_idP];
538

539
540
541
542
543
544
545
546
547
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    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;
    *ul_req = *ul_req_tmp;
    // 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;
548

549
    if (ul_req->ul_config_request_body.number_of_pdus>0) {
550
      LOG_D(MAC, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
551
    }
552

553
554
555
    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));
556
  }
557
558
}

Thomas Laurent's avatar
Thomas Laurent committed
559
#include <openair1/PHY/LTE_TRANSPORT/transport_proto.h>
560

561
void
562
563
eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
                          frame_t frameP,
564
                          sub_frame_t subframeP) {
565
566
  int               mbsfn_status[MAX_NUM_CCs];
  protocol_ctxt_t   ctxt;
567
568
569
570
  rnti_t            rnti  = 0;
  int               CC_id = 0;
  int               UE_id = -1;
  eNB_MAC_INST      *eNB                    = RC.mac[module_idP];
571
  UE_info_t         *UE_info                = &(eNB->UE_info);
572
  COMMON_channels_t *cc                     = eNB->common_channels;
573
  UE_sched_ctrl_t     *UE_scheduling_control  = NULL;
574
575
576
577
  start_meas(&(eNB->eNB_scheduler));
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_IN);
  eNB->frame    = frameP;
  eNB->subframe = subframeP;
578

579
580
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    mbsfn_status[CC_id] = 0;
581
    /* Clear vrb_maps */
582
583
    memset(cc[CC_id].vrb_map, 0, 100);
    memset(cc[CC_id].vrb_map_UL, 0, 100);
584
    cc[CC_id].mcch_active = 0;
585
    clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, subframeP);
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

    /* hack: skip BCH RBs in subframe 0 for DL scheduling,
     *       because with high MCS we may exceed code rate 0.93
     *       when using those RBs (36.213 7.1.7 says the UE may
     *       skip decoding if the code rate is higher than 0.93)
     * TODO: remove this hack, deal with physical bits properly
     *       i.e. reduce MCS in the scheduler if code rate > 0.93
     */
    if (subframeP == 0) {
      int i;
      int bw = cc[CC_id].mib->message.dl_Bandwidth;
      /* start and count defined for RBs: 6, 15, 25, 50, 75, 100 */
      int start[6] = { 0, 4, 9, 22, 34, 47 };
      int count[6] = { 6, 7, 7,  6,  7,  6 };
      for (i = 0; i < count[bw]; i++)
        cc[CC_id].vrb_map[start[bw] + i] = 1;
    }
603
  }
604

605
606
  /* Refresh UE list based on UEs dropped by PHY in previous subframe */
  for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
607
    if (UE_info->active[UE_id]) {
608
609
      rnti = UE_RNTI(module_idP, UE_id);
      CC_id = UE_PCCID(module_idP, UE_id);
610
      UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
611

612
/* to be merged with MAC_stats.log generation. probably redundant
613
      if (((frameP & 127) == 0) && (subframeP == 0)) {
HARADA Masayuki's avatar
HARADA Masayuki committed
614
615
616
617
618
619
620
621
        double total_bler;
        if(UE_scheduling_control->pusch_rx_num[CC_id] == 0 && UE_scheduling_control->pusch_rx_error_num[CC_id] == 0) {
          total_bler = 0;
        }
        else {
          total_bler = (double)UE_scheduling_control->pusch_rx_error_num[CC_id] / (double)(UE_scheduling_control->pusch_rx_error_num[CC_id] + UE_scheduling_control->pusch_rx_num[CC_id]) * 100;
        }
        LOG_I(MAC,"UE %x : %s, PHR %d DLCQI %d PUSCH %d PUCCH %d RLC disc %d UL-stat rcv %lu err %lu bler %lf mcsoff %d bsr %u sched %u tbs %lu cnt %u , DL-stat tbs %lu cnt %u rb %u buf %u 1st %u ret %u ri %d\n",
622
623
              rnti,
              UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync",
624
              UE_info->UE_template[CC_id][UE_id].phr_info,
625
              UE_scheduling_control->dl_cqi[CC_id],
626
              UE_scheduling_control->pusch_snr_avg[CC_id],
HARADA Masayuki's avatar
HARADA Masayuki committed
627
628
629
630
631
632
633
634
635
636
637
638
639
640
              UE_scheduling_control->pucch1_snr[CC_id],
              UE_scheduling_control->rlc_out_of_resources_cnt,
              UE_scheduling_control->pusch_rx_num[CC_id],
              UE_scheduling_control->pusch_rx_error_num[CC_id],
              total_bler,
              UE_scheduling_control->mcs_offset[CC_id],
              UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer,
              UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used,
#if defined(PRE_SCD_THREAD)
HARADA Masayuki's avatar
HARADA Masayuki committed
641
              UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
HARADA Masayuki's avatar
HARADA Masayuki committed
642
643
644
645
646
647
648
#else
              0,
#endif
              UE_scheduling_control->first_cnt[CC_id],
              UE_scheduling_control->ret_cnt[CC_id],
              UE_scheduling_control->aperiodic_ri_received[CC_id]
        );
649
      }
650
*/
651
652
      RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = -63;

653
      if (UE_id == UE_info->list.head) {
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP]);
      }

      /* Set and increment CDRX related timers */
      if (UE_scheduling_control->cdrx_configured == TRUE) {
        boolean_t harq_active_time_condition = FALSE;
        UE_TEMPLATE *UE_template = NULL;
        unsigned long active_time_condition = 0; // variable used only for tracing purpose

        /* (UL and DL) HARQ RTT timers and DRX retransmission timers */
        for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
          /* DL asynchronous HARQ process */
          if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > 0) {
            UE_scheduling_control->drx_retransmission_timer[harq_process_id]++;

            if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > UE_scheduling_control->drx_retransmission_timer_thres[harq_process_id]) {
              UE_scheduling_control->drx_retransmission_timer[harq_process_id] = 0;
            }
          }

          if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 0) {
            UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id]++;

            if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 8) {
              /* Note: here drx_retransmission_timer is restarted instead of started in the specification */
              UE_scheduling_control->drx_retransmission_timer[harq_process_id] = 1; // started when HARQ RTT timer expires
              UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] = 0;
            }
          }

684
          /* UL asynchronous HARQ process: only UL HARQ RTT timer is implemented (hence not implemented) */
685
686
687
688
          if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 0) {
            UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id]++;

            if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 4) {
689
              /*
690
691
692
               * TODO: implement the handling of UL asynchronous HARQ
               * drx_ULRetransmissionTimer should be (re)started here
               */
693
694
695
696
              UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] = 0;
            }
          }

697
          /* UL synchronous HARQ process */
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
          if (UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] > 0) {
            UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id]++;

            if (UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] > 5) {
              harq_active_time_condition = TRUE;
              UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] = 0;
              active_time_condition = 5; // for tracing purpose
            }
          }
        }

        /* On duration timer */
        if (UE_scheduling_control->on_duration_timer > 0) {
          UE_scheduling_control->on_duration_timer++;

          if (UE_scheduling_control->on_duration_timer > UE_scheduling_control->on_duration_timer_thres) {
            UE_scheduling_control->on_duration_timer = 0;
          }
        }

        /* DRX inactivity timer */
        if (UE_scheduling_control->drx_inactivity_timer > 0) {
          UE_scheduling_control->drx_inactivity_timer++;

          if (UE_scheduling_control->drx_inactivity_timer > (UE_scheduling_control->drx_inactivity_timer_thres + 1)) {
723
            /* Note: the +1 on the threshold is due to information in table C-1 of 36.321 */
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
            UE_scheduling_control->drx_inactivity_timer = 0;

            /* When timer expires switch into short or long DRX cycle */
            if (UE_scheduling_control->drx_shortCycle_timer_thres > 0) {
              UE_scheduling_control->in_short_drx_cycle = TRUE;
              UE_scheduling_control->drx_shortCycle_timer = 0;
              UE_scheduling_control->in_long_drx_cycle = FALSE;
            } else {
              UE_scheduling_control->in_long_drx_cycle = TRUE;
            }
          }
        }

        /* Short DRX Cycle */
        if (UE_scheduling_control->in_short_drx_cycle == TRUE) {
          UE_scheduling_control->drx_shortCycle_timer++;

741
          /* When the Short DRX cycles are over, switch to long DRX cycle */
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
          if (UE_scheduling_control->drx_shortCycle_timer > UE_scheduling_control->drx_shortCycle_timer_thres) {
            UE_scheduling_control->drx_shortCycle_timer = 0;
            UE_scheduling_control->in_short_drx_cycle = FALSE;
            UE_scheduling_control->in_long_drx_cycle = TRUE;
            UE_scheduling_control->drx_longCycle_timer = 0;
          }
        } else {
          UE_scheduling_control->drx_shortCycle_timer = 0;
        }

        /* Long DRX Cycle */
        if (UE_scheduling_control->in_long_drx_cycle == TRUE) {
          UE_scheduling_control->drx_longCycle_timer++;

          if (UE_scheduling_control->drx_longCycle_timer > UE_scheduling_control->drx_longCycle_timer_thres) {
            UE_scheduling_control->drx_longCycle_timer = 1;
          }
        } else {
          UE_scheduling_control->drx_longCycle_timer = 0;
        }

763
        /* Check for error cases */
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
        if ((UE_scheduling_control->in_short_drx_cycle == TRUE) && (UE_scheduling_control->in_long_drx_cycle == TRUE)) {
          LOG_E(MAC, "Error in C-DRX: UE id %d is in both short and long DRX cycle. Should not happen. Back it to long cycle only\n", UE_id);
          UE_scheduling_control->in_short_drx_cycle = FALSE;
        }

        /* Condition to start On Duration Timer */
        if (UE_scheduling_control->in_short_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) {
          if (((frameP * 10) + subframeP) % (UE_scheduling_control->short_drx_cycle_duration) ==
              (UE_scheduling_control->drx_start_offset) % (UE_scheduling_control->short_drx_cycle_duration)) {
            UE_scheduling_control->on_duration_timer = 1;
          }
        } else if (UE_scheduling_control->in_long_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) {
          if (((frameP * 10) + subframeP) % (UE_scheduling_control->drx_longCycle_timer_thres) ==
              (UE_scheduling_control->drx_start_offset)) {
            UE_scheduling_control->on_duration_timer = 1;
          }
        }

        /* Update Active Time status of UE
         * Based on 36.321 5.7 the differents conditions for the UE to be in Acttive Should be check ONLY
         * here for the current subframe. The variable 'UE_scheduling_control->in_active_time' should be updated
         * ONLY here. The variable can then be used for testing the actual state of the UE for scheduling purpose.
         */
787
        UE_template = &(UE_info->UE_template[CC_id][UE_id]);
788

789
        /* (a)synchronous HARQ processes handling for Active Time */
790
791
792
        for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
          if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > 0) {
            harq_active_time_condition = TRUE;
793
            active_time_condition = 2; // for tracing purpose
794
795
796
797
            break;
          }
        }

798
        /* Active time conditions */
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
        if (UE_scheduling_control->on_duration_timer > 0 ||
            UE_scheduling_control->drx_inactivity_timer > 1 ||
            harq_active_time_condition ||
            UE_template->ul_SR > 0) {
          UE_scheduling_control->in_active_time = TRUE;
        } else {
          UE_scheduling_control->in_active_time = FALSE;
        }

        /* BEGIN VCD */
        if (UE_id == 0) {
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_ON_DURATION_TIMER, (unsigned long) UE_scheduling_control->on_duration_timer);
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) UE_scheduling_control->drx_inactivity_timer);
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_SHORT_CYCLE, (unsigned long) UE_scheduling_control->drx_shortCycle_timer);
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_LONG_CYCLE, (unsigned long) UE_scheduling_control->drx_longCycle_timer);
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) UE_scheduling_control->drx_retransmission_timer[0]);
          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME, (unsigned long) UE_scheduling_control->in_active_time);

817
          /* For tracing purpose */
818
819
820
821
          if (UE_template->ul_SR > 0) {
            active_time_condition = 1;
          } else if ((UE_scheduling_control->on_duration_timer > 0) && (active_time_condition == 0)) {
            active_time_condition = 3;
822
          } else if ((UE_scheduling_control->drx_inactivity_timer > 1) && (active_time_condition == 0)) {
823
824
825
826
827
            active_time_condition = 4;
          }

          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME_CONDITION, (unsigned long) active_time_condition);
        }
828

829
        /* END VCD */
830

831
        /* DCI0 ongoing timer */
832
        if (UE_scheduling_control->dci0_ongoing_timer > 0) {
833
834
835
836
837
          if (UE_scheduling_control->dci0_ongoing_timer > 7) {
            UE_scheduling_control->dci0_ongoing_timer = 0;
          } else {
            UE_scheduling_control->dci0_ongoing_timer++;
          }
838
        }
839
840
      } else { // else: CDRX not configured
        /* Note: (UL) HARQ RTT timers processing is done here and can be used by other features than CDRX */
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
        /* HARQ RTT timers */
        for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
          if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 0) {
            UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id]++;

            if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 8) {
              UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] = 0;
            }
          }

          if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 0) {
            UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id]++;

            if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 4) {
              UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] = 0;
            }
          }
        } // end loop harq process
      } // end else CDRX not configured

      /* Increment these timers, they are cleared when we receive an sdu */
      UE_scheduling_control->ul_inactivity_timer++;
      UE_scheduling_control->cqi_req_timer++;
      LOG_D(MAC, "UE %d/%x : ul_inactivity %d, cqi_req %d\n",
            UE_id,
            rnti,
            UE_scheduling_control->ul_inactivity_timer,
            UE_scheduling_control->cqi_req_timer);
      check_ul_failure(module_idP, CC_id, UE_id, frameP, subframeP);

      if (UE_scheduling_control->ue_reestablishment_reject_timer > 0) {
        UE_scheduling_control->ue_reestablishment_reject_timer++;

        if (UE_scheduling_control->ue_reestablishment_reject_timer >= UE_scheduling_control->ue_reestablishment_reject_timer_thres) {
          UE_scheduling_control->ue_reestablishment_reject_timer = 0;

          /* Clear reestablish_rnti_map */
          if (UE_scheduling_control->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;
              }
            }
887

888
889
890
891
            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);
          }
892
893

          /* Note: This should not be done in the MAC! */
894
	  /*
895
896
897
898
          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)) {
Cedric Roux's avatar
Cedric Roux committed
899
              void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
900
901
902
903
904
905
906
907
908
              LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti);
              clean_eNb_ulsch(ulsch);
            }
          }

          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)) {
Cedric Roux's avatar
Cedric Roux committed
909
              void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
910
911
912
913
              LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti);
              clean_eNb_dlsch(dlsch);
            }
          }
914
915
916
917
918
919
920
921
922
923
924
	  */

	int id;

	// clean ULSCH entries for rnti
	id = find_ulsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
        if (id>=0) clean_eNb_ulsch(RC.eNB[module_idP][CC_id]->ulsch[id]);

	// clean DLSCH entries for rnti
	id = find_dlsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
        if (id>=0) clean_eNb_dlsch(RC.eNB[module_idP][CC_id]->dlsch[id][0]);
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942

          for (int j = 0; j < 10; j++) {
            nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
            ul_req_tmp = &(eNB->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],
943
                           (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
944
945
946
947
948
949
950
951
952
953
954
955
956
                  }

                  ul_req_tmp->number_of_pdus--;
                }
              } // end for pdu_index
            } // end if (ul_req_tmp)
          } // end for j

          rrc_mac_remove_ue(module_idP,rnti);
        } // end if (UE_scheduling_control->ue_reestablishment_reject_timer >= UE_scheduling_control->ue_reestablishment_reject_timer_thres)
      } // end if (UE_scheduling_control->ue_reestablishment_reject_timer > 0)
    } // end if UE active
  } // end for loop on UE_id
957

958
#if (!defined(PRE_SCD_THREAD))
959
  if (!NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
Cedric Roux's avatar
Cedric Roux committed
960
    void rlc_tick(int, int);
961
    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP);
Cedric Roux's avatar
Cedric Roux committed
962
    rlc_tick(frameP, subframeP);
963
964
965
966
    pdcp_run(&ctxt);
    pdcp_mbms_run(&ctxt);
    rrc_rx_tx(&ctxt, CC_id);
  }
967
#endif
968

969
  int do_fembms_si=0;
970
971
972
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    if (cc[CC_id].MBMS_flag > 0) {
      start_meas(&RC.mac[module_idP]->schedule_mch);
973
974
975
976
977
      int(*schedule_mch)(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframe) = NULL;
      schedule_mch = schedule_MBMS_NFAPI;
      if(schedule_mch){
      	mbsfn_status[CC_id] = schedule_mch(module_idP, CC_id, frameP, subframeP);
      }
978
      stop_meas(&RC.mac[module_idP]->schedule_mch);
knopp's avatar
   
knopp committed
979
    }
980
981
982
983
    if (cc[CC_id].FeMBMS_flag > 0) {
	do_fembms_si = 1;
    }

984
  }
985

986
987
988
989
990
  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 (eNB->scheduler_mode == SCHED_MODE_DEFAULT) {
991
992
    schedule_ulsch_p = schedule_ulsch;
    schedule_ue_spec_p = schedule_dlsch;
993
  } else if (eNB->scheduler_mode == SCHED_MODE_FAIR_RR) {
994
995
996
997
    memset(dlsch_ue_select, 0, sizeof(dlsch_ue_select));
    schedule_ulsch_p = schedule_ulsch_fairRR;
    schedule_ue_spec_p = schedule_ue_spec_fairRR;
  }
998

999
  if(debug_flag == 0) {
1000
1001
    LOG_E(MAC,"SCHED_MODE = %d\n", eNB->scheduler_mode);
    debug_flag = 1;
1002
1003
  }

1004
  /* This schedules MIB */
1005
1006
1007
1008
1009
1010
1011
1012
1013
  if(!do_fembms_si/*get_softmodem_params()->fembms*/){
    if ((subframeP == 0) && (frameP & 3) == 0)
      schedule_mib(module_idP, frameP, subframeP);
  }else{
    if ((subframeP == 0) && (frameP & 15) == 0 ){
       schedule_fembms_mib(module_idP, frameP, subframeP);
       //schedule_SI_MBMS(module_idP, frameP, subframeP);
    }
  }
1014

1015
1016
  if (get_softmodem_params()->phy_test == 0) {
    /* This schedules SI for legacy LTE and eMTC starting in subframeP */
1017
1018
1019
1020
    if(!do_fembms_si/*get_softmodem_params()->fembms*/)
       schedule_SI(module_idP, frameP, subframeP);
    else
       schedule_SI_MBMS(module_idP, frameP, subframeP);
1021
    /* This schedules Paging in subframeP */
1022
    schedule_PCH(module_idP,frameP,subframeP);
1023
    /* This schedules Random-Access for legacy LTE and eMTC starting in subframeP */
1024
    schedule_RA(module_idP, frameP, subframeP);
1025
    /* Copy previously scheduled UL resources (ULSCH + HARQ) */
1026
    copy_ulreq(module_idP, frameP, subframeP);
1027
    /* This schedules SRS in subframeP */
1028
    schedule_SRS(module_idP, frameP, subframeP);
1029
1030

    /* This schedules ULSCH in subframeP (dci0) */
1031
    if (schedule_ulsch_p != NULL) {
1032
      schedule_ulsch_p(module_idP, frameP, subframeP);
1033
    } else {
1034