enb_app.c 9.41 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
55
#endif

#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)

56
/*------------------------------------------------------------------------------*/
winckel's avatar
winckel committed
57
58
#define ENB_REGISTER_RETRY_DELAY 10

59
60
61
62
/*------------------------------------------------------------------------------*/
static uint32_t enb_nb = 1;

/*------------------------------------------------------------------------------*/
winckel's avatar
winckel committed
63
64
static uint32_t eNB_app_register()
{
65
66
67
68
69
70
71
72
73
74
    uint32_t eNB_id_start = 0;
    uint32_t eNB_id_end = 1;
    uint32_t eNB_id;
    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;
#   endif
winckel's avatar
winckel committed
75

76
77
78
79
80
81
82
    for (eNB_id = eNB_id_start; (eNB_id < eNB_id_end)
#   if defined(OAI_EMU)
            && (oai_emulation.info.cli_start_enb[eNB_id] == 1)
#   endif
            ; eNB_id++)
    {
        char *mme_address_v4;
winckel's avatar
winckel committed
83

84
85
86
87
88
89
90
91
92
93
94
        if (EPC_MODE_ENABLED)
        {
            mme_address_v4 = EPC_MODE_MME_ADDRESS;
        }
        else
        {
            mme_address_v4 = "192.168.12.87";
        }
        char *mme_address_v6 = "2001:660:5502:12:30da:829a:2343:b6cf";
        s1ap_register_enb_req_t *s1ap_register_eNB;
        uint32_t hash;
winckel's avatar
winckel committed
95

96
97
        //note:  there is an implicit relationship between the data struct and the message name
        msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
winckel's avatar
winckel committed
98

99
        s1ap_register_eNB = &S1AP_REGISTER_ENB_REQ(msg_p);
winckel's avatar
winckel committed
100

101
102
103
104
105
106
107
108
109
110
111
112
113
        hash = s1ap_generate_eNB_id ();

        /* Some default/random parameters */
        s1ap_register_eNB->eNB_id = eNB_id + (hash & 0xFFFF8);
        s1ap_register_eNB->cell_type = CELL_MACRO_ENB;
        s1ap_register_eNB->tac = 0;
        s1ap_register_eNB->mcc = 208;
        s1ap_register_eNB->mnc = 34;
        s1ap_register_eNB->default_drx = PAGING_DRX_256;

        s1ap_register_eNB->nb_mme = 1;
        s1ap_register_eNB->mme_ip_address[0].ipv4 = 1;
        s1ap_register_eNB->mme_ip_address[0].ipv6 = 0;
114
115
        strncpy (s1ap_register_eNB->mme_ip_address[0].ipv4_address, mme_address_v4, sizeof(s1ap_register_eNB->mme_ip_address[0].ipv4_address));
        strncpy (s1ap_register_eNB->mme_ip_address[0].ipv6_address, mme_address_v6, sizeof(s1ap_register_eNB->mme_ip_address[0].ipv6_address));
winckel's avatar
winckel committed
116
117

#   if defined ENB_APP_ENB_REGISTER_2_MME
118
119
120
121
        s1ap_register_eNB->nb_mme = 2;
        s1ap_register_eNB->mme_ip_address[1].ipv4 = 1;
        s1ap_register_eNB->mme_ip_address[1].ipv6 = 0;
        mme_address_v4 = "192.168.12.88";
122
123
        strncpy(s1ap_register_eNB->mme_ip_address[1].ipv4_address, mme_address_v4, sizeof(s1ap_register_eNB->mme_ip_address[1].ipv4_address));
        strncpy(s1ap_register_eNB->mme_ip_address[1].ipv6_address, mme_address_v6, sizeof(s1ap_register_eNB->mme_ip_address[1].ipv6_address));
winckel's avatar
winckel committed
124
125
#   endif

126
        itti_send_msg_to_task (TASK_S1AP, eNB_id, msg_p);
winckel's avatar
winckel committed
127

128
129
        register_enb_pending++;
    }
winckel's avatar
winckel committed
130

131
    return register_enb_pending;
winckel's avatar
winckel committed
132
133
134
135
}
# endif
#endif

136
137
138
/*------------------------------------------------------------------------------*/
void *eNB_app_task(void *args_p)
{
winckel's avatar
winckel committed
139
140
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
141
142
143
144
145
146
147
148
149
    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;
    instance_t instance;
    itti_mark_task_ready (TASK_ENB_APP);

150
151
# if defined(ENABLE_USE_MME)
#   if defined(OAI_EMU)
152
    enb_nb = oai_emulation.info.nb_enb_local;
153
#   endif
winckel's avatar
winckel committed
154
155
156
# endif

# if defined(ENABLE_USE_MME)
157
158
159
    /* Try to register each eNB */
    registered_enb = 0;
    register_enb_pending = eNB_app_register ();
winckel's avatar
winckel committed
160
# else
161
162
163
    /* 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
164
165
# endif

166
167
168
169
    do
    {
        // Wait for a message
        itti_receive_msg (TASK_ENB_APP, &msg_p);
winckel's avatar
winckel committed
170

171
172
        msg_name = ITTI_MSG_NAME (msg_p);
        instance = ITTI_MSG_INSTANCE (msg_p);
winckel's avatar
winckel committed
173

174
175
176
177
178
        switch (ITTI_MSG_ID(msg_p))
        {
            case TERMINATE_MESSAGE:
                itti_exit_task ();
                break;
winckel's avatar
winckel committed
179

180
            case MESSAGE_TEST:
181
                LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
182
                break;
winckel's avatar
winckel committed
183
184

# if defined(ENABLE_USE_MME)
185
            case S1AP_REGISTER_ENB_CNF:
186
187
                LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name,
                      S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

                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);
208
209
210
211
212
213
214
215
216
217

#   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
218
219
220
221
222
                    }
                    else
                    {
                        uint32_t not_associated = enb_nb - registered_enb;

223
                        LOG_W(ENB_APP, " %d eNB %s not associated with a MME, retrying registration in %d seconds ...\n",
224
225
226
227
228
229
                              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)
                        {
230
                            LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"usleep\" instead!\n");
231
232
233
234
235

                            usleep(ENB_REGISTER_RETRY_DELAY * 1000000);
                            /* Restart the registration process */
                            registered_enb = 0;
                            register_enb_pending = eNB_app_register ();
236
237
238
239
240
                        }
                    }
                }
                break;

241
242
243
244
245
246
247
            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;

248
            case TIMER_HAS_EXPIRED:
249
                LOG_I(ENB_APP, " Received %s: timer_id %d\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);
250
251
252
253
254
255
256
257

                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
258
259
# endif

260
            default:
261
                LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name);
262
263
                break;
        }
winckel's avatar
winckel committed
264

265
        itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
266
    } while (1);
winckel's avatar
winckel committed
267
268
#endif

269
    return NULL;
winckel's avatar
winckel committed
270
}