enb_app.c 12.8 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
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 23 24
/*
                                enb_app.c
                             -------------------
25
  AUTHOR  : Laurent Winckel, Sebastien ROUX, Lionel GAUTHIER, Navid Nikaein
26
  COMPANY : EURECOM
27
  EMAIL   : Lionel.Gauthier@eurecom.fr and Navid Nikaein
28
*/
winckel's avatar
winckel committed
29 30

#include <string.h>
Lionel Gauthier's avatar
 
Lionel Gauthier committed
31
#include <stdio.h>
winckel's avatar
winckel committed
32 33

#include "enb_app.h"
34
#include "enb_config.h"
winckel's avatar
winckel committed
35
#include "assertions.h"
36
#include "common/ran_context.h"
winckel's avatar
winckel committed
37

38
#include "common/utils/LOG/log.h"
winckel's avatar
winckel committed
39 40 41 42 43 44

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
#   include "sctp_eNB_task.h"
45
#   include "gtpv1u_eNB_task.h"
frtabu's avatar
frtabu committed
46 47
# else
#    define EPC_MODE_ENABLED 0
winckel's avatar
winckel committed
48
# endif
49

50 51 52 53
//#   include "x2ap_eNB.h"
#   include "x2ap_messages_types.h"
#   define X2AP_ENB_REGISTER_RETRY_DELAY   10

54
#include "openair1/PHY/INIT/phy_init.h"
55
extern unsigned char NB_eNB_INST;
winckel's avatar
winckel committed
56 57
#endif

58 59
extern RAN_CONTEXT_t RC;

winckel's avatar
winckel committed
60 61
#if defined(ENABLE_ITTI)

62
/*------------------------------------------------------------------------------*/
63 64 65
# if defined(ENABLE_USE_MME)
#   define ENB_REGISTER_RETRY_DELAY 10
# endif
winckel's avatar
winckel committed
66

67 68
#include "targets/RT/USER/lte-softmodem.h"

69
/*------------------------------------------------------------------------------*/
70 71

/*
72
static void configure_phy(module_id_t enb_id, const Enb_properties_array_t* enb_properties)
73
{
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  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];
  }

90
  itti_send_msg_to_task (TASK_PHY_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
91
}
92
*/
93 94

/*------------------------------------------------------------------------------*/
95
static void configure_rrc(uint32_t enb_id)
96
{
97
  MessageDef *msg_p = NULL;
98
  //  int CC_id;
99 100 101

  msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);

102
  if (RC.rrc[enb_id]) {
Cedric Roux's avatar
Cedric Roux committed
103
    RCconfig_RRC(msg_p,enb_id, RC.rrc[enb_id]);
104 105 106 107
    

    LOG_I(ENB_APP,"Sending configuration message to RRC task\n");
    itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
108

109 110
  }
  else AssertFatal(0,"RRC context for eNB %d not allocated\n",enb_id);
111 112
}

113
/*------------------------------------------------------------------------------*/
114
# if defined(ENABLE_USE_MME)
115
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
116
{
117 118 119
  uint32_t         enb_id;
  MessageDef      *msg_p;
  uint32_t         register_enb_pending = 0;
120

121 122 123 124 125
  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
    {
      /* 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);

126 127 128 129
      RCconfig_S1(msg_p, enb_id);

      if (enb_id == 0) RCconfig_gtpu();

130
      LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
131

132 133
      LOG_I(ENB_APP,"[eNB %d] eNB_app_register for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));

134
      itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
135 136

      register_enb_pending++;
137
    }
138
  }
winckel's avatar
winckel committed
139

140
  return register_enb_pending;
winckel's avatar
winckel committed
141 142 143 144
}
# endif
#endif

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
/*------------------------------------------------------------------------------*/
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end)
{
  uint32_t         enb_id;
  MessageDef      *msg_p;
  uint32_t         register_enb_x2_pending = 0;

  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {

    {

      msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);

      RCconfig_X2(msg_p, enb_id);

	//itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);

      register_enb_x2_pending++;
    }
  }

  return register_enb_x2_pending;
}

169 170 171
/*------------------------------------------------------------------------------*/
void *eNB_app_task(void *args_p)
{
winckel's avatar
winckel committed
172
#if defined(ENABLE_ITTI)
173
  uint32_t                        enb_nb = RC.nb_inst; 
174 175
  uint32_t                        enb_id_start = 0;
  uint32_t                        enb_id_end = enb_id_start + enb_nb;
winckel's avatar
winckel committed
176
# if defined(ENABLE_USE_MME)
177
  uint32_t                        register_enb_pending=0;
178 179
  uint32_t                        registered_enb;
  long                            enb_register_retry_timer_id;
180
# endif
181 182 183
  uint32_t                        x2_register_enb_pending;
  //uint32_t                        x2_registered_enb;
  //long                            x2_enb_register_retry_timer_id;
184
  uint32_t                        enb_id;
185 186 187
  MessageDef                     *msg_p           = NULL;
  instance_t                      instance;
  int                             result;
Cedric Roux's avatar
Cedric Roux committed
188 189 190
  /* for no gcc warnings */
  (void)instance;

191
  itti_mark_task_ready (TASK_ENB_APP);
192

193 194
  LOG_I(PHY, "%s() Task ready initialise structures\n", __FUNCTION__);

195 196 197 198
  RCconfig_L1();

  RCconfig_macrlc();

199
  LOG_I(PHY, "%s() RC.nb_L1_inst:%d\n", __FUNCTION__, RC.nb_L1_inst);
winckel's avatar
winckel committed
200

201
  if (RC.nb_L1_inst>0) AssertFatal(l1_north_init_eNB()==0,"could not initialize L1 north interface\n");
202

203
  AssertFatal (enb_nb <= RC.nb_inst,
204
               "Number of eNB is greater than eNB defined in configuration file (%d/%d)!",
205 206 207 208 209
               enb_nb, RC.nb_inst);

  LOG_I(ENB_APP,"Allocating eNB_RRC_INST for %d instances\n",RC.nb_inst);

  RC.rrc = (eNB_RRC_INST **)malloc(RC.nb_inst*sizeof(eNB_RRC_INST *));
210
  LOG_I(PHY, "%s() RC.nb_inst:%d RC.rrc:%p\n", __FUNCTION__, RC.nb_inst, RC.rrc);
211

212 213
  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
    RC.rrc[enb_id] = (eNB_RRC_INST*)malloc(sizeof(eNB_RRC_INST));
214
    LOG_I(PHY, "%s() Creating RRC instance RC.rrc[%d]:%p (%d of %d)\n", __FUNCTION__, enb_id, RC.rrc[enb_id], enb_id+1, enb_id_end);
215 216 217
    memset((void *)RC.rrc[enb_id],0,sizeof(eNB_RRC_INST));
    configure_rrc(enb_id);
  }
218

winckel's avatar
winckel committed
219
# if defined(ENABLE_USE_MME)
220
  /* Try to register each eNB */
221 222
    registered_enb = 0;
    register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
frtabu's avatar
frtabu committed
223
#else
224
  /* Start L2L1 task */
225 226
    msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
    itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
frtabu's avatar
frtabu committed
227
#endif
winckel's avatar
winckel committed
228

229 230 231
  /* Try to register each eNB with each other */
 // x2_registered_enb = 0;
  x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
winckel's avatar
winckel committed
232

233 234 235
  do {
    // Wait for a message
    itti_receive_msg (TASK_ENB_APP, &msg_p);
winckel's avatar
winckel committed
236

237
    instance = ITTI_MSG_INSTANCE (msg_p);
winckel's avatar
winckel committed
238

239 240
    switch (ITTI_MSG_ID(msg_p)) {
    case TERMINATE_MESSAGE:
241
      LOG_W(ENB_APP, " *** Exiting ENB_APP thread\n");
242 243
      itti_exit_task ();
      break;
winckel's avatar
winckel committed
244

245 246 247
    case MESSAGE_TEST:
      LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
      break;
winckel's avatar
winckel committed
248

249 250 251 252
    case SOFT_RESTART_MESSAGE:
      handle_reconfiguration(instance);
      break;

253
    case S1AP_REGISTER_ENB_CNF:
frtabu's avatar
frtabu committed
254
# if defined(ENABLE_USE_MME)
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
  	LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
  	      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);

  	  } else {
  	    LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n",
  		  enb_nb - registered_enb,  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);
  	    }
  	  }
  	}
frtabu's avatar
frtabu committed
291
#endif
292 293 294
      break;

    case S1AP_DEREGISTERED_ENB_IND:
295 296 297
      if (EPC_MODE_ENABLED) {
  	LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
  	      S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme);
298

299 300
  	/* TODO handle recovering of registration */
      }
301 302 303
      break;

    case TIMER_HAS_EXPIRED:
frtabu's avatar
frtabu committed
304
# if defined(ENABLE_USE_MME)
305
  	LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
306

307 308 309 310 311
  	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);
  	}
frtabu's avatar
frtabu committed
312
#endif
313
      break;
314

winckel's avatar
winckel committed
315

316
    default:
317
      LOG_E(ENB_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
318 319 320 321 322 323
      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
324 325 326

#endif

Cedric Roux's avatar
Cedric Roux committed
327

328
  return NULL;
winckel's avatar
winckel committed
329
}
330 331 332 333 334 335 336

void handle_reconfiguration(module_id_t mod_id)
{
  struct timespec start, end;
  clock_gettime(CLOCK_MONOTONIC, &start);
  flexran_agent_info_t *flexran = RC.flexran[mod_id];

337
  LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
338

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
  if (ENB_WAIT == flexran->node_ctrl_state) {
    /* this is already waiting, just release */
    pthread_mutex_lock(&flexran->mutex_node_ctrl);
    flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
    pthread_cond_signal(&flexran->cond_node_ctrl);
    return;
  }

  if (stop_L1L2(mod_id) < 0) {
    LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
    return;
  }

  /* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
   * executed by the FlexRAN thread */
  if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
356
    LOG_I(ENB_APP, " * eNB %d: Waiting for FlexRAN RTController command *\n", mod_id);
357 358 359 360 361 362 363 364
    pthread_mutex_lock(&flexran->mutex_node_ctrl);
    flexran->node_ctrl_state = ENB_WAIT;
    while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
      pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
  }

  if (restart_L1L2(mod_id) < 0) {
365
    LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
366 367 368 369 370 371 372 373 374 375 376 377
    itti_terminate_tasks(TASK_PHY_ENB);
    return;
  }

  clock_gettime(CLOCK_MONOTONIC, &end);
  end.tv_sec -= start.tv_sec;
  if (end.tv_nsec >= start.tv_nsec) {
    end.tv_nsec -= start.tv_nsec;
  } else {
    end.tv_sec -= 1;
    end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
  }
378
  LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
379
}