enb_app.c 14.1 KB
Newer Older
winckel's avatar
winckel committed
1
2
/*******************************************************************************

3
4
 Eurecom OpenAirInterface
 Copyright(c) 1999 - 2012 Eurecom
winckel's avatar
winckel committed
5

6
7
8
 This program is free software; you can redistribute it and/or modify it
 under the terms and conditions of the GNU General Public License,
 version 2, as published by the Free Software Foundation.
winckel's avatar
winckel committed
9

10
11
12
13
 This program is distributed in the hope 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.
winckel's avatar
winckel committed
14

15
16
17
 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
winckel's avatar
winckel committed
18

19
20
 The full GNU General Public License is included in this distribution in
 the file called "COPYING".
winckel's avatar
winckel committed
21

22
23
24
25
26
27
 Contact Information
 Openair Admin: openair_admin@eurecom.fr
 Openair Tech : openair_tech@eurecom.fr
 Forums       : http://forums.eurecom.fr/openairinterface
 Address      : EURECOM, Campus SophiaTech, 450 Route des Chappes
 06410 Biot FRANCE
winckel's avatar
winckel committed
28

29
 *******************************************************************************/
winckel's avatar
winckel committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#include <string.h>

#include "enb_app.h"
#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"
# endif
49
50

extern unsigned char NB_eNB_INST;
winckel's avatar
winckel committed
51
52
53
54
#endif

#if defined(ENABLE_ITTI)

55
/*------------------------------------------------------------------------------*/
56
57
58
# if defined(ENABLE_USE_MME)
#   define ENB_REGISTER_RETRY_DELAY 10
# endif
winckel's avatar
winckel committed
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
typedef struct mme_ip_address_s {
    unsigned ipv4:1;
    unsigned ipv6:1;
    char *ipv4_address;
    char *ipv6_address;
} mme_ip_address_t;

typedef struct Enb_properties_s {
    /* Unique eNB_id to identify the eNB within EPC.
     * For macro eNB ids this field should be 20 bits long.
     * For home eNB ids this field should be 28 bits long.
     */
    uint32_t eNB_id;

    /* The type of the cell */
    enum cell_type_e cell_type;

    /* Optional name for the cell
     * NOTE: the name can be NULL (i.e no name) and will be cropped to 150
     * characters.
     */
    char *eNB_name;

    /* Tracking area code */
    uint16_t tac;

    /* Mobile Country Code
     * Mobile Network Code
     */
    uint16_t mcc;
    uint16_t mnc;

    /* Default Paging DRX of the eNB as defined in TS 36.304 */
    paging_drx_t default_drx;

    /* Nb of MME to connect to */
    uint8_t          nb_mme;
    /* List of MME to connect to */
    mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
} Enb_properties_t;

101
/*------------------------------------------------------------------------------*/
102
# if defined(ENABLE_USE_MME)
103
static uint32_t enb_nb = 1; /* Default number of eNB */
104
# endif
105
106
107
108
109
110
111

/* eNB 0 properties */
static Enb_properties_t enb_0_properties =
{
    347472,
    CELL_MACRO_ENB,
    "eNB_Eurecom_0",
winckel's avatar
winckel committed
112
113
    1,      /* Tracking area code, 0x0000 and 0xfffe are reserved values */
    208,    /* Mobile Country Code */
114
#ifdef EXMIMO_IOT
winckel's avatar
winckel committed
115
    92,     /* Mobile Network Code */
116
#else
winckel's avatar
winckel committed
117
    10,     /* Mobile Network Code */
118
#endif
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    PAGING_DRX_256,
    1, /* There are 2 addresses defined, but use only one by default */
    {
        {
            1,
            0,
            "192.168.12.87",
            "2001:660:5502:12:30da:829a:2343:b6cf"
        },
        {
            1,
            0,
            "192.168.12.86",
            ""
        }
    }
};

/* eNB 1 properties */
static Enb_properties_t enb_1_properties =
{
    347473,
    CELL_MACRO_ENB,
    "eNB_Eurecom_1",
winckel's avatar
winckel committed
143
    1,
144
    208,
145
    92,
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    PAGING_DRX_256,
    1, /* There are 2 addresses defined, but use only one by default */
    {
        {
            1,
            0,
            "192.168.12.87",
            "2001:660:5502:12:30da:829a:2343:b6cf"
        },
        {
            1,
            0,
            "192.168.12.88",
            ""
        }
    }
};

164
165
166
167
168
169
/* eNB 2 properties */
static Enb_properties_t enb_2_properties =
{
    347474,
    CELL_MACRO_ENB,
    "eNB_Eurecom_2",
winckel's avatar
winckel committed
170
    1,
171
    208,
172
    92,
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    PAGING_DRX_256,
    1,
    {
        {
            1,
            0,
            "192.168.12.87",
            "2001:660:5502:12:30da:829a:2343:b6cf"
        },
    }
};

/* eNB 3 properties */
static Enb_properties_t enb_3_properties =
{
    347475,
    CELL_MACRO_ENB,
    "eNB_Eurecom_3",
winckel's avatar
winckel committed
191
    1,
192
    208,
193
    92,
194
195
196
197
198
199
200
201
202
203
204
205
    PAGING_DRX_256,
    1,
    {
        {
            1,
            0,
            "192.168.12.87",
            "2001:660:5502:12:30da:829a:2343:b6cf"
        },
    }
};

206
207
208
209
static Enb_properties_t *enb_properties[] =
{
    &enb_0_properties,
    &enb_1_properties,
210
211
    &enb_2_properties,
    &enb_3_properties,
212
};
213
214

/*------------------------------------------------------------------------------*/
winckel's avatar
winckel committed
215
static void configure_rrc(void)
winckel's avatar
winckel committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
{
    uint32_t eNB_id_start = 0;
    uint32_t eNB_id_end = 1;
    uint32_t eNB_id;
    MessageDef *msg_p;

#   if defined(OAI_EMU)
    eNB_id_start = oai_emulation.info.first_enb_local;
    eNB_id_end = oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local;
#   endif

    for (eNB_id = eNB_id_start; (eNB_id < eNB_id_end) ; eNB_id++)
    {
        msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);

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

        itti_send_msg_to_task (TASK_RRC_ENB, eNB_id, msg_p);
    }
}

240
# if defined(ENABLE_USE_MME)
winckel's avatar
winckel committed
241
242
static uint32_t eNB_app_register()
{
243
244
245
    uint32_t eNB_id_start = 0;
    uint32_t eNB_id_end = 1;
    uint32_t eNB_id;
246
    uint32_t mme_id;
247
248
249
250
251
252
    MessageDef *msg_p;
    uint32_t register_enb_pending = 0;

#   if defined(OAI_EMU)
    eNB_id_start = oai_emulation.info.first_enb_local;
    eNB_id_end = oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local;
winckel's avatar
winckel committed
253

254
    DevCheck(eNB_id_end <= NUMBER_OF_eNB_MAX, eNB_id_end, NUMBER_OF_eNB_MAX, 0);
winckel's avatar
winckel committed
255
#   endif
256
    DevCheck(eNB_id_end <= (sizeof(enb_properties) / sizeof(enb_properties[0])), eNB_id_end, (sizeof(enb_properties) / sizeof(enb_properties[0])), 0);
257
258
259

    for (eNB_id = eNB_id_start; (eNB_id < eNB_id_end) ; eNB_id++)
    {
260
#   if defined(OAI_EMU)
261
        if (oai_emulation.info.cli_start_enb[eNB_id] == 1)
262
263
#   endif
        {
264
265
266
267
268
269
270
271
272
273
            s1ap_register_enb_req_t *s1ap_register_eNB;
            uint32_t hash;

            /* Overwrite default eNB ID */
            hash = s1ap_generate_eNB_id ();
            enb_properties[eNB_id]->eNB_id = eNB_id + (hash & 0xFFFF8);

            if (EPC_MODE_ENABLED)
            {
                /* Overwrite default IP v4 address by value from command line */
winckel's avatar
winckel committed
274
                enb_properties[eNB_id]->mme_ip_address[0].ipv4_address = EPC_MODE_MME_ADDRESS;
275
276
277
278
279
280
281
282
283
284
            }

            /* 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[eNB_id]->eNB_id;
            s1ap_register_eNB->cell_type = enb_properties[eNB_id]->cell_type;
winckel's avatar
winckel committed
285
            s1ap_register_eNB->eNB_name = enb_properties[eNB_id]->eNB_name;
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
            s1ap_register_eNB->tac = enb_properties[eNB_id]->tac;
            s1ap_register_eNB->mcc = enb_properties[eNB_id]->mcc;
            s1ap_register_eNB->mnc = enb_properties[eNB_id]->mnc;
            s1ap_register_eNB->default_drx = enb_properties[eNB_id]->default_drx;

            s1ap_register_eNB->nb_mme = enb_properties[eNB_id]->nb_mme;
            DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, eNB_id, s1ap_register_eNB->nb_mme, S1AP_MAX_NB_MME_IP_ADDRESS);

            for (mme_id = 0; mme_id < s1ap_register_eNB->nb_mme; mme_id++)
            {
                s1ap_register_eNB->mme_ip_address[mme_id].ipv4 = enb_properties[eNB_id]->mme_ip_address[mme_id].ipv4;
                s1ap_register_eNB->mme_ip_address[mme_id].ipv6 = enb_properties[eNB_id]->mme_ip_address[mme_id].ipv6;
                strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv4_address,
                         enb_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[eNB_id]->mme_ip_address[mme_id].ipv6_address,
                         sizeof(s1ap_register_eNB->mme_ip_address[0].ipv6_address));
            }

            itti_send_msg_to_task (TASK_S1AP, eNB_id, msg_p);

            register_enb_pending++;
309
310
        }
    }
winckel's avatar
winckel committed
311

312
    return register_enb_pending;
winckel's avatar
winckel committed
313
314
315
316
}
# endif
#endif

317
318
319
/*------------------------------------------------------------------------------*/
void *eNB_app_task(void *args_p)
{
winckel's avatar
winckel committed
320
321
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
322
323
324
325
326
327
    static uint32_t register_enb_pending;
    static uint32_t registered_enb;
    static long enb_register_retry_timer_id;
# endif
    MessageDef *msg_p;
    const char *msg_name;
328
329
330
    instance_t  instance;
    int         result;

331
332
    itti_mark_task_ready (TASK_ENB_APP);

333
334
# if defined(ENABLE_USE_MME)
#   if defined(OAI_EMU)
335
    enb_nb = oai_emulation.info.nb_enb_local;
336
#   endif
winckel's avatar
winckel committed
337
338
# endif

winckel's avatar
winckel committed
339
340
    configure_rrc();

winckel's avatar
winckel committed
341
# if defined(ENABLE_USE_MME)
342
343
344
    /* Try to register each eNB */
    registered_enb = 0;
    register_enb_pending = eNB_app_register ();
winckel's avatar
winckel committed
345
# else
346
347
348
    /* 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
349
350
# endif

351
352
353
354
    do
    {
        // Wait for a message
        itti_receive_msg (TASK_ENB_APP, &msg_p);
winckel's avatar
winckel committed
355

356
357
        msg_name = ITTI_MSG_NAME (msg_p);
        instance = ITTI_MSG_INSTANCE (msg_p);
winckel's avatar
winckel committed
358

359
360
361
362
363
        switch (ITTI_MSG_ID(msg_p))
        {
            case TERMINATE_MESSAGE:
                itti_exit_task ();
                break;
winckel's avatar
winckel committed
364

365
            case MESSAGE_TEST:
366
                LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
367
                break;
winckel's avatar
winckel committed
368
369

# if defined(ENABLE_USE_MME)
370
            case S1AP_REGISTER_ENB_CNF:
371
372
                LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name,
                      S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

                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);
393
394
395
396
397
398
399
400
401
402

#   if defined(OAI_EMU)
                        /* If 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);
                        }
#   endif
403
404
405
406
407
                    }
                    else
                    {
                        uint32_t not_associated = enb_nb - registered_enb;

408
                        LOG_W(ENB_APP, " %d eNB %s not associated with a MME, retrying registration in %d seconds ...\n",
409
410
411
412
413
414
                              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)
                        {
415
                            LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
416

417
                            sleep(ENB_REGISTER_RETRY_DELAY);
418
419
420
                            /* Restart the registration process */
                            registered_enb = 0;
                            register_enb_pending = eNB_app_register ();
421
422
423
424
425
                        }
                    }
                }
                break;

426
427
428
429
430
431
432
            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;

433
            case TIMER_HAS_EXPIRED:
434
                LOG_I(ENB_APP, " Received %s: timer_id %d\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);
435
436
437
438
439
440
441
442

                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 ();
                }
                break;
winckel's avatar
winckel committed
443
444
# endif

445
            default:
446
                LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name);
447
448
                break;
        }
winckel's avatar
winckel committed
449

450
451
        result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
452
    } while (1);
winckel's avatar
winckel committed
453
454
#endif

455
    return NULL;
winckel's avatar
winckel committed
456
}