enb_app.c 21.9 KB
Newer Older
winckel's avatar
winckel committed
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
nikaeinn's avatar
nikaeinn committed
27

28
*******************************************************************************/
nikaeinn's avatar
nikaeinn committed
29

30
31
32
/*
                                enb_app.c
                             -------------------
nikaeinn's avatar
nikaeinn committed
33
  AUTHOR  : Laurent Winckel, Sebastien ROUX, Lionel GAUTHIER, Navid Nikaein
34
  COMPANY : EURECOM
nikaeinn's avatar
nikaeinn committed
35
  EMAIL   : Lionel.Gauthier@eurecom.fr and Navid Nikaein
36
*/
winckel's avatar
winckel committed
37
38

#include <string.h>
gauthier's avatar
   
gauthier committed
39
#include <stdio.h>
winckel's avatar
winckel committed
40
41

#include "enb_app.h"
42
#include "enb_config.h"
winckel's avatar
winckel committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "assertions.h"

#include "log.h"
#if defined(OAI_EMU)
# include "OCG.h"
# include "OCG_extern.h"
#endif

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# include "timer.h"
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
#   include "sctp_eNB_task.h"
57
#   include "gtpv1u_eNB_task.h"
winckel's avatar
winckel committed
58
# endif
59
60

extern unsigned char NB_eNB_INST;
winckel's avatar
winckel committed
61
62
63
64
#endif

#if defined(ENABLE_ITTI)

65
/*------------------------------------------------------------------------------*/
66
67
68
# if defined(ENABLE_USE_MME)
#   define ENB_REGISTER_RETRY_DELAY 10
# endif
winckel's avatar
winckel committed
69

70
/*------------------------------------------------------------------------------*/
71
static void configure_phy(module_id_t enb_id, const Enb_properties_array_t* enb_properties)
72
{
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  MessageDef *msg_p;
  int CC_id;

  msg_p = itti_alloc_new_message (TASK_ENB_APP, PHY_CONFIGURATION_REQ);

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    PHY_CONFIGURATION_REQ (msg_p).frame_type[CC_id]              = enb_properties->properties[enb_id]->frame_type[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).prefix_type[CC_id]             = enb_properties->properties[enb_id]->prefix_type[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).downlink_frequency[CC_id]      = enb_properties->properties[enb_id]->downlink_frequency[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).uplink_frequency_offset[CC_id] = enb_properties->properties[enb_id]->uplink_frequency_offset[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).nb_antennas_tx[CC_id]          = enb_properties->properties[enb_id]->nb_antennas_tx[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).nb_antennas_rx[CC_id]          = enb_properties->properties[enb_id]->nb_antennas_rx[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).tx_gain[CC_id]                 = enb_properties->properties[enb_id]->tx_gain[CC_id];
    PHY_CONFIGURATION_REQ (msg_p).rx_gain[CC_id]                 = enb_properties->properties[enb_id]->rx_gain[CC_id];
  }

89
  itti_send_msg_to_task (TASK_PHY_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
90
}
91
92

/*------------------------------------------------------------------------------*/
winckel's avatar
winckel committed
93
static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_properties)
winckel's avatar
winckel committed
94
{
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  MessageDef *msg_p = NULL;
  int CC_id;

  msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);

  RRC_CONFIGURATION_REQ (msg_p).cell_identity =   enb_properties->properties[enb_id]->eNB_id;
  RRC_CONFIGURATION_REQ (msg_p).tac =             enb_properties->properties[enb_id]->tac;
  RRC_CONFIGURATION_REQ (msg_p).mcc =             enb_properties->properties[enb_id]->mcc;
  RRC_CONFIGURATION_REQ (msg_p).mnc =             enb_properties->properties[enb_id]->mnc;
  RRC_CONFIGURATION_REQ (msg_p).mnc_digit_length = enb_properties->properties[enb_id]->mnc_digit_length;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    RRC_CONFIGURATION_REQ (msg_p).frame_type[CC_id]                               = enb_properties->properties[enb_id]->frame_type[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).tdd_config[CC_id]                               = enb_properties->properties[enb_id]->tdd_config[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).tdd_config_s[CC_id]                             = enb_properties->properties[enb_id]->tdd_config_s[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).eutra_band[CC_id]                               = enb_properties->properties[enb_id]->eutra_band[CC_id];

    // RACH-Config
    RRC_CONFIGURATION_REQ (msg_p).rach_numberOfRA_Preambles[CC_id]                = enb_properties->properties[enb_id]->rach_numberOfRA_Preambles[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_preamblesGroupAConfig[CC_id]               = enb_properties->properties[enb_id]->rach_preamblesGroupAConfig[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_sizeOfRA_PreamblesGroupA[CC_id]            = enb_properties->properties[enb_id]->rach_sizeOfRA_PreamblesGroupA[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_messageSizeGroupA[CC_id]                   = enb_properties->properties[enb_id]->rach_messageSizeGroupA[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_messagePowerOffsetGroupB[CC_id]            = enb_properties->properties[enb_id]->rach_messagePowerOffsetGroupB[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_powerRampingStep[CC_id]                    = enb_properties->properties[enb_id]->rach_powerRampingStep[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_preambleInitialReceivedTargetPower[CC_id]  = enb_properties->properties[enb_id]->rach_preambleInitialReceivedTargetPower[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_preambleTransMax[CC_id]                    = enb_properties->properties[enb_id]->rach_preambleTransMax[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_raResponseWindowSize[CC_id]                = enb_properties->properties[enb_id]->rach_raResponseWindowSize[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_macContentionResolutionTimer[CC_id]        = enb_properties->properties[enb_id]->rach_macContentionResolutionTimer[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).rach_maxHARQ_Msg3Tx[CC_id]                      = enb_properties->properties[enb_id]->rach_maxHARQ_Msg3Tx[CC_id];

    // BCCH-Config
    RRC_CONFIGURATION_REQ (msg_p).bcch_modificationPeriodCoeff[CC_id]             = enb_properties->properties[enb_id]->bcch_modificationPeriodCoeff[CC_id];

    // PCCH-Config
    RRC_CONFIGURATION_REQ (msg_p).pcch_defaultPagingCycle[CC_id]                  = enb_properties->properties[enb_id]->pcch_defaultPagingCycle[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pcch_nB[CC_id]                                  = enb_properties->properties[enb_id]->pcch_nB[CC_id];

    // PRACH-Config
    RRC_CONFIGURATION_REQ (msg_p).prach_root[CC_id]                               = enb_properties->properties[enb_id]->prach_root[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).prach_config_index[CC_id]                       = enb_properties->properties[enb_id]->prach_config_index[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).prach_high_speed[CC_id]                         = enb_properties->properties[enb_id]->prach_high_speed[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).prach_zero_correlation[CC_id]                   = enb_properties->properties[enb_id]->prach_zero_correlation[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).prach_freq_offset[CC_id]                        = enb_properties->properties[enb_id]->prach_freq_offset[CC_id];

    // PDSCH-Config
    RRC_CONFIGURATION_REQ (msg_p).pdsch_referenceSignalPower[CC_id]               = enb_properties->properties[enb_id]->pdsch_referenceSignalPower[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pdsch_p_b[CC_id]                                = enb_properties->properties[enb_id]->pdsch_p_b[CC_id];

    // PUSCH-Config
    RRC_CONFIGURATION_REQ (msg_p).pusch_n_SB[CC_id]                               = enb_properties->properties[enb_id]->pusch_n_SB[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_hoppingMode[CC_id]                        = enb_properties->properties[enb_id]->pusch_hoppingMode[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_hoppingOffset[CC_id]                      = enb_properties->properties[enb_id]->pusch_hoppingOffset[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_enable64QAM[CC_id]                        = enb_properties->properties[enb_id]->pusch_enable64QAM[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_groupHoppingEnabled[CC_id]                = enb_properties->properties[enb_id]->pusch_groupHoppingEnabled[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_groupAssignment[CC_id]                    = enb_properties->properties[enb_id]->pusch_groupAssignment[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_sequenceHoppingEnabled[CC_id]             = enb_properties->properties[enb_id]->pusch_sequenceHoppingEnabled[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_nDMRS1[CC_id]                             = enb_properties->properties[enb_id]->pusch_nDMRS1[CC_id];

    // PUCCH-Config

    RRC_CONFIGURATION_REQ (msg_p).pucch_delta_shift[CC_id]                        = enb_properties->properties[enb_id]->pucch_delta_shift[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_nRB_CQI[CC_id]                            = enb_properties->properties[enb_id]->pucch_nRB_CQI[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_nCS_AN[CC_id]                             = enb_properties->properties[enb_id]->pucch_nCS_AN[CC_id];
158
#ifndef Rel10
159
    RRC_CONFIGURATION_REQ (msg_p).pucch_n1_AN[CC_id]                              = enb_properties->properties[enb_id]->pucch_n1_AN[CC_id];
160
#endif
knopp's avatar
knopp committed
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    // SRS Config
    RRC_CONFIGURATION_REQ (msg_p).srs_enable[CC_id]                               = enb_properties->properties[enb_id]->srs_enable[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).srs_BandwidthConfig[CC_id]                      = enb_properties->properties[enb_id]->srs_BandwidthConfig[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).srs_SubframeConfig[CC_id]                       = enb_properties->properties[enb_id]->srs_SubframeConfig[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).srs_ackNackST[CC_id]                            = enb_properties->properties[enb_id]->srs_ackNackST[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).srs_MaxUpPts[CC_id]                             = enb_properties->properties[enb_id]->srs_MaxUpPts[CC_id];

    // uplinkPowerControlCommon

    RRC_CONFIGURATION_REQ (msg_p).pusch_p0_Nominal[CC_id]                         = enb_properties->properties[enb_id]->pusch_p0_Nominal[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_p0_Nominal[CC_id]                         = enb_properties->properties[enb_id]->pucch_p0_Nominal[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pusch_alpha[CC_id]                              = enb_properties->properties[enb_id]->pusch_alpha[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_deltaF_Format1[CC_id]                     = enb_properties->properties[enb_id]->pucch_deltaF_Format1[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_deltaF_Format1b[CC_id]                    = enb_properties->properties[enb_id]->pucch_deltaF_Format1b[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_deltaF_Format2[CC_id]                     = enb_properties->properties[enb_id]->pucch_deltaF_Format2[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_deltaF_Format2a[CC_id]                    = enb_properties->properties[enb_id]->pucch_deltaF_Format2a[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).pucch_deltaF_Format2b[CC_id]                    = enb_properties->properties[enb_id]->pucch_deltaF_Format2b[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).msg3_delta_Preamble[CC_id]                      = enb_properties->properties[enb_id]->msg3_delta_Preamble[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ul_CyclicPrefixLength[CC_id]                    = enb_properties->properties[enb_id]->ul_CyclicPrefixLength[CC_id];

    // UE Timers and Constants

    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t300[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_t300[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t301[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_t301[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t310[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_t310[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_n310[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_n310[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_t311[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_t311[CC_id];
    RRC_CONFIGURATION_REQ (msg_p).ue_TimersAndConstants_n311[CC_id]               = enb_properties->properties[enb_id]->ue_TimersAndConstants_n311[CC_id];
  }

192
  itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
winckel's avatar
winckel committed
193
194
}

195
/*------------------------------------------------------------------------------*/
196
# if defined(ENABLE_USE_MME)
winckel's avatar
winckel committed
197
static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
winckel's avatar
winckel committed
198
{
199
200
201
202
203
204
  uint32_t         enb_id;
  uint32_t         mme_id;
  MessageDef      *msg_p;
  uint32_t         register_enb_pending = 0;
  char            *str                  = NULL;
  struct in_addr   addr;
205
206

#   if defined(OAI_EMU)
winckel's avatar
winckel committed
207

winckel's avatar
winckel committed
208
#   endif
209

210
  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
211
#   if defined(OAI_EMU)
212
213

    if (oai_emulation.info.cli_start_enb[enb_id] == 1)
214
#   endif
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    {
      s1ap_register_enb_req_t *s1ap_register_eNB;

      /* note:  there is an implicit relationship between the data structure and the message name */
      msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);

      s1ap_register_eNB = &S1AP_REGISTER_ENB_REQ(msg_p);

      /* Some default/random parameters */
      s1ap_register_eNB->eNB_id           = enb_properties->properties[enb_id]->eNB_id;
      s1ap_register_eNB->cell_type        = enb_properties->properties[enb_id]->cell_type;
      s1ap_register_eNB->eNB_name         = enb_properties->properties[enb_id]->eNB_name;
      s1ap_register_eNB->tac              = enb_properties->properties[enb_id]->tac;
      s1ap_register_eNB->mcc              = enb_properties->properties[enb_id]->mcc;
      s1ap_register_eNB->mnc              = enb_properties->properties[enb_id]->mnc;
      s1ap_register_eNB->mnc_digit_length = enb_properties->properties[enb_id]->mnc_digit_length;
      s1ap_register_eNB->default_drx      = enb_properties->properties[enb_id]->pcch_defaultPagingCycle[0];

      s1ap_register_eNB->nb_mme =         enb_properties->properties[enb_id]->nb_mme;
234
235
      AssertFatal (s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, "Too many MME for eNB %d (%d/%d)!", enb_id, s1ap_register_eNB->nb_mme,
                   S1AP_MAX_NB_MME_IP_ADDRESS);
236
237
238
239
240
241
242
243
244
245
246
247

      for (mme_id = 0; mme_id < s1ap_register_eNB->nb_mme; mme_id++) {
        s1ap_register_eNB->mme_ip_address[mme_id].ipv4 = enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv4;
        s1ap_register_eNB->mme_ip_address[mme_id].ipv6 = enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv6;
        strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv4_address,
                 enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv4_address,
                 sizeof(s1ap_register_eNB->mme_ip_address[0].ipv4_address));
        strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv6_address,
                 enb_properties->properties[enb_id]->mme_ip_address[mme_id].ipv6_address,
                 sizeof(s1ap_register_eNB->mme_ip_address[0].ipv6_address));
      }

248
249
250
251
      s1ap_register_eNB->sctp_in_streams       = enb_properties->properties[enb_id]->sctp_in_streams;
      s1ap_register_eNB->sctp_out_streams      = enb_properties->properties[enb_id]->sctp_out_streams;


252
253
254
255
256
257
      s1ap_register_eNB->enb_ip_address.ipv6 = 0;
      s1ap_register_eNB->enb_ip_address.ipv4 = 1;
      addr.s_addr = enb_properties->properties[enb_id]->enb_ipv4_address_for_S1_MME;
      str = inet_ntoa(addr);
      strcpy(s1ap_register_eNB->enb_ip_address.ipv4_address, str);

258
      itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
259
260

      register_enb_pending++;
261
    }
262
  }
winckel's avatar
winckel committed
263

264
  return register_enb_pending;
winckel's avatar
winckel committed
265
266
267
268
}
# endif
#endif

269
270
271
/*------------------------------------------------------------------------------*/
void *eNB_app_task(void *args_p)
{
272
  const Enb_properties_array_t   *enb_properties_p  = NULL;
winckel's avatar
winckel committed
273
#if defined(ENABLE_ITTI)
274
275
276
  uint32_t                        enb_nb = 1; /* Default number of eNB is 1 */
  uint32_t                        enb_id_start = 0;
  uint32_t                        enb_id_end = enb_id_start + enb_nb;
winckel's avatar
winckel committed
277
# if defined(ENABLE_USE_MME)
278
279
280
  uint32_t                        register_enb_pending;
  uint32_t                        registered_enb;
  long                            enb_register_retry_timer_id;
281
# endif
282
283
284
285
286
  uint32_t                        enb_id;
  MessageDef                     *msg_p           = NULL;
  const char                     *msg_name        = NULL;
  instance_t                      instance;
  int                             result;
287

Cedric Roux's avatar
Cedric Roux committed
288
289
290
  /* for no gcc warnings */
  (void)instance;

291
  itti_mark_task_ready (TASK_ENB_APP);
292

293
294
# if defined(ENABLE_USE_MME)
#   if defined(OAI_EMU)
295
296
297
  enb_nb =        oai_emulation.info.nb_enb_local;
  enb_id_start =  oai_emulation.info.first_enb_local;
  enb_id_end =    oai_emulation.info.first_enb_local + enb_nb;
298

299
300
301
  AssertFatal (enb_id_end <= NUMBER_OF_eNB_MAX,
               "Last eNB index is greater or equal to maximum eNB index (%d/%d)!",
               enb_id_end, NUMBER_OF_eNB_MAX);
302
#   endif
winckel's avatar
winckel committed
303
304
# endif

305
  enb_properties_p = enb_config_get();
306

307
308
309
  AssertFatal (enb_nb <= enb_properties_p->number,
               "Number of eNB is greater than eNB defined in configuration file (%d/%d)!",
               enb_nb, enb_properties_p->number);
310

311
312
313
314
  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
    configure_phy(enb_id, enb_properties_p);
    configure_rrc(enb_id, enb_properties_p);
  }
winckel's avatar
winckel committed
315

winckel's avatar
winckel committed
316
# if defined(ENABLE_USE_MME)
317
318
319
  /* Try to register each eNB */
  registered_enb = 0;
  register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
winckel's avatar
winckel committed
320
# else
321
322
323
  /* Start L2L1 task */
  msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
  itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
winckel's avatar
winckel committed
324
325
# endif

326
327
328
  do {
    // Wait for a message
    itti_receive_msg (TASK_ENB_APP, &msg_p);
winckel's avatar
winckel committed
329

330
331
    msg_name = ITTI_MSG_NAME (msg_p);
    instance = ITTI_MSG_INSTANCE (msg_p);
winckel's avatar
winckel committed
332

333
334
335
336
    switch (ITTI_MSG_ID(msg_p)) {
    case TERMINATE_MESSAGE:
      itti_exit_task ();
      break;
winckel's avatar
winckel committed
337

338
339
340
    case MESSAGE_TEST:
      LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
      break;
winckel's avatar
winckel committed
341
342

# if defined(ENABLE_USE_MME)
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

    case S1AP_REGISTER_ENB_CNF:
      LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name,
            S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);

      DevAssert(register_enb_pending > 0);
      register_enb_pending--;

      /* Check if at least eNB is registered with one MME */
      if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) {
        registered_enb++;
      }

      /* Check if all register eNB requests have been processed */
      if (register_enb_pending == 0) {
        if (registered_enb == enb_nb) {
          /* If all eNB are registered, start L2L1 task */
          MessageDef *msg_init_p;

          msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
          itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
364
365

#   if defined(OAI_EMU)
366
367
368
369
370
371
372
373

          /* Also inform all NAS UE tasks */
          for (instance = NB_eNB_INST + oai_emulation.info.first_ue_local;
               instance < (NB_eNB_INST + oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local); instance ++) {
            msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
            itti_send_msg_to_task (TASK_NAS_UE, instance, msg_init_p);
          }

374
#   endif
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
        } else {
          uint32_t not_associated = enb_nb - registered_enb;

          LOG_W(ENB_APP, " %d eNB %s not associated with a MME, retrying registration in %d seconds ...\n",
                not_associated, not_associated > 1 ? "are" : "is", ENB_REGISTER_RETRY_DELAY);

          /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
          if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
                           NULL, &enb_register_retry_timer_id) < 0) {
            LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");

            sleep(ENB_REGISTER_RETRY_DELAY);
            /* Restart the registration process */
            registered_enb = 0;
            register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
          }
        }
      }

      break;

    case S1AP_DEREGISTERED_ENB_IND:
      LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name,
            S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme);

      /* TODO handle recovering of registration */
      break;

    case TIMER_HAS_EXPIRED:
      LOG_I(ENB_APP, " Received %s: timer_id %d\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);

      if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
        /* Restart the registration process */
        registered_enb = 0;
        register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
      }

      break;
winckel's avatar
winckel committed
413
414
# endif

415
416
417
418
419
420
421
422
    default:
      LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name);
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  } while (1);
winckel's avatar
winckel committed
423
424
425

#endif

Cedric Roux's avatar
Cedric Roux committed
426
427
428
  /* for no gcc warnings */
  (void)enb_properties_p;

429
  return NULL;
winckel's avatar
winckel committed
430
}