lte-softmodem.c 21.4 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 21
 * 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
 */

22
/*! \file lte-softmodem.c
23
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
 
Raymond Knopp committed
25 26 27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
Raymond Knopp's avatar
 
Raymond Knopp committed
29 30 31
 * \note
 * \warning
 */
32

33

Cedric Roux's avatar
Cedric Roux committed
34 35 36
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

37
#include "rt_wrapper.h"
38

39

40 41
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

42
#include "assertions.h"
43
#include "msc.h"
44 45

#include "PHY/types.h"
46

47
#include "PHY/defs_eNB.h"
48
#include "common/ran_context.h"
49
#include "common/config/config_userapi.h"
oai's avatar
oai committed
50
#include "common/utils/load_module_shlib.h"
51
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
Raymond Knopp's avatar
 
Raymond Knopp committed
52
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
53

Raymond Knopp's avatar
 
Raymond Knopp committed
54
#include "../../ARCH/COMMON/common_lib.h"
55
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
56

Raymond Knopp's avatar
 
Raymond Knopp committed
57
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
58

59 60 61
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
62

63 64 65 66
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
67
#include "PHY/TOOLS/phy_scope_interface.h"
frtabu's avatar
frtabu committed
68
#include "nfapi/oai_integration/vendor_ext.h"
69 70 71 72
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
73
#include "common/utils/LOG/log.h"
Navid Nikaein's avatar
Navid Nikaein committed
74
#include "UTIL/OTG/otg_tx.h"
75
#include "UTIL/OTG/otg_externs.h"
76
#include "UTIL/MATH/oml.h"
77
#include "common/utils/LOG/vcd_signal_dumper.h"
78
#include "UTIL/OPT/opt.h"
79
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
80
//#include "PHY/TOOLS/time_meas.h"
81

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
82
#ifndef OPENAIR2
83
  #include "UTIL/OTG/otg_vars.h"
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
84 85
#endif

86 87 88

#include "create_tasks.h"

89

90 91
#include "PHY/INIT/phy_init.h"

92 93
#include "system.h"

94

95
#include "lte-softmodem.h"
oai's avatar
oai committed
96
#include "NB_IoT_interface.h"
97

frtabu's avatar
frtabu committed
98

99 100 101 102 103
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex


104 105
uint16_t sf_ahead=4;

Raymond Knopp's avatar
 
Raymond Knopp committed
106 107
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
108
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
109
int config_sync_var=-1;
110

Raymond Knopp's avatar
Raymond Knopp committed
111
volatile int             oai_exit = 0;
112

113
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
114
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
115

116
int UE_scan = 1;
117
int UE_scan_carrier = 0;
118
runmode_t mode = normal_txrx;
frtabu's avatar
frtabu committed
119

120 121
FILE *input_fd=NULL;

122

123 124
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
125 126
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
127 128 129 130
#else
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
Lionel Gauthier's avatar
Lionel Gauthier committed
131
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
132

133
double rx_gain_off = 0.0;
134

Raymond Knopp's avatar
 
Raymond Knopp committed
135
double sample_rate=30.72e6;
136
double bw = 10.0e6;
137

Florian Kaltenberger's avatar
Florian Kaltenberger committed
138

139 140 141
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

142 143
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
144

Raymond Knopp's avatar
 
Raymond Knopp committed
145 146 147
char ref[128] = "internal";
char channels[128] = "0";

laurent's avatar
laurent committed
148 149
int rx_input_level_dBm;
int    otg_enabled;
150 151
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
152

153
extern void init_eNB_afterRU(void);
laurent's avatar
laurent committed
154
extern void  phy_free_RU(RU_t *);
155

156
int transmission_mode=1;
157
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
158
int numerology = 0;
159

laurent's avatar
laurent committed
160
THREAD_STRUCT thread_struct;
161 162
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;
163 164
double cpuf;

165 166 167
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

168
void signal_handler(int sig) {
169 170 171 172 173 174 175 176 177 178
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
179
  } else {
180 181
    printf("Linux signal %s...\n",strsignal(sig));
    exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n");
182 183
  }
}
184

185
void exit_function(const char *file, const char *function, const int line, const char *s) {
186
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
187

188
  if (s != NULL) {
189
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
190 191 192
  }

  oai_exit = 1;
193

194 195
  if (RC.ru == NULL)
    exit(-1); // likely init not completed, prevent crash or hang, exit now...
196

197 198 199 200
  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
    if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) {
      RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
      RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
201 202
    }

203 204 205 206 207
    if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
      RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
      RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
    }
  }
208

209 210
  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
211
}
212

213
static void get_options(void) {
214
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
215
  get_common_options();
216
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
oai's avatar
oai committed
217

218
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
219 220 221 222
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    RCConfig();
    NB_eNB_INST = RC.nb_inst;
laurent's avatar
laurent committed
223
    LOG_I(ENB_APP,"Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
224

225
    if (!IS_SOFTMODEM_NONBIOT) {
226
      load_NB_IoT();
laurent's avatar
laurent committed
227
      LOG_I(ENB_APP,"           nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
228 229 230 231 232 233
             RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst);
    } else {
      printf("All Nb-IoT instances disabled\n");
      RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=0;
    }
  }
234 235
}

236
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
237 238 239
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
240
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
241 242 243 244 245 246 247 248 249 250
    /* Set some default values that may be overwritten while reading options */
    frame_parms[CC_id]->frame_type          = FDD;
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
    frame_parms[CC_id]->Ncp                 = NORMAL;
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = 0;
    frame_parms[CC_id]->num_MBSFN_config    = 0;
251
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
    frame_parms[CC_id]->nushift             = 0;
    frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
    frame_parms[CC_id]->phich_config_common.phich_duration = normal;
    // UL RS Config
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
267 268 269 270
    //    downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
    //    downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
    //    downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
    //    downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
271
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
272
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
273 274 275
  }
}

276
void wait_RUs(void) {
277 278
  /* do not modify the following LOG_UI message, which is used by CI */
  LOG_UI(ENB_APP,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
279 280
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
281

282 283
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
284
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
285 286
  }

287
  pthread_mutex_unlock(&RC.ru_mutex);
288 289 290
  LOG_I(PHY,"RUs configured\n");
}

291
void wait_eNBs(void) {
292 293 294 295
  int i,j;
  int waiting=1;

  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
296 297
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
298
    waiting=0;
299

300
    for (i=0; i<RC.nb_L1_inst; i++) {
301 302
      printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);

303 304 305 306 307
      for (j=0; j<RC.nb_L1_CC[i]; j++) {
        if (RC.eNB[i][j]->configured==0) {
          waiting=1;
          break;
        }
308 309
      }
    }
310
  }
311

312 313
  printf("eNB L1 are configured\n");
}
314

315

316 317
/*
 * helper function to terminate a certain ITTI task
318
 */
319
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
320
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
321
        itti_get_task_name(from), from, itti_get_task_name(to), to);
322
  MessageDef *msg;
323 324
  msg = itti_alloc_new_message (from, TERMINATE_MESSAGE);
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
325 326
}

327
extern void  free_transport(PHY_VARS_eNB *);
328
extern void  phy_free_RU(RU_t *);
329

330
int stop_L1L2(module_id_t enb_id) {
331 332
  LOG_W(ENB_APP, "stopping lte-softmodem\n");

333
  if (!RC.ru) {
334
    LOG_UI(ENB_APP, "no RU configured\n");
335 336 337
    return -1;
  }

338
  /* these tasks need to pick up new configuration */
339
  terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
Robert Schmidt's avatar
Robert Schmidt committed
340
  oai_exit = 1;
341
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
Robert Schmidt's avatar
Robert Schmidt committed
342
  kill_RU_proc(RC.ru[enb_id]);
343
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
344
  kill_eNB_proc(enb_id);
345
  oai_exit = 0;
346

347 348 349 350
  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) {
    free_transport(RC.eNB[enb_id][cc_id]);
    phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
  }
351

352
  phy_free_RU(RC.ru[enb_id]);
353
  free_lte_top();
354 355 356 357
  return 0;
}

/*
358
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
359
 */
360
int restart_L1L2(module_id_t enb_id) {
361 362 363
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
364 365
  LOG_W(ENB_APP, "restarting lte-softmodem\n");
  /* block threads */
366
  pthread_mutex_lock(&sync_mutex);
367
  sync_var = -1;
368
  pthread_mutex_unlock(&sync_mutex);
369

370 371
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
372 373
  }

374 375 376 377 378
  RC.ru_mask |= (1 << ru->idx);
  /* copy the changed frame parameters to the RU */
  /* TODO this should be done for all RUs associated to this eNB */
  memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
  set_function_spec_param(RC.ru[enb_id]);
379 380 381
  /* reset the list of connected UEs in the MAC, since in this process with
   * loose all UEs (have to reconnect) */
  init_UE_list(&RC.mac[enb_id]->UE_list);
382
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
383

384 385 386 387 388 389 390
  if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
    LOG_E(RRC, "Create task for RRC eNB failed\n");
    return -1;
  } else {
    LOG_I(RRC, "Re-created task for RRC eNB successfully\n");
  }

391 392 393 394 395
  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
  msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ);
  RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
396 397
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
398 399 400 401 402 403
  wait_eNBs();
  init_RU_proc(ru);
  ru->rf_map.card = 0;
  ru->rf_map.chain = 0; /* CC_id + chain_offset;*/
  wait_RUs();
  init_eNB_afterRU();
404 405 406 407 408 409
  printf("Sending sync to all threads\n");
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
  return 0;
410
}
411

412 413 414 415
void init_pdcp(void) {
  if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
    pdcp_layer_init();
    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
416 417
                             (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;

418 419
    if (IS_SOFTMODEM_NOS1)
      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
420

421 422 423
    pdcp_module_init(pdcp_initmask);

    if (NODE_IS_CU(RC.rrc[0]->node_type)) {
424
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
425
    } else {
426 427
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
      pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
428 429
    }
  } else {
430
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
431 432
  }
}
433

434
static  void wait_nfapi_init(char *thread_name) {
435 436
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
437

438 439
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
440

441
  pthread_mutex_unlock(&nfapi_sync_mutex);
442
  printf( "NFAPI: got sync (%s)\n", thread_name);
443 444
}

445
int main( int argc, char **argv ) {
446
  int i;
447
  int CC_id = 0;
448
  int ru_id;
449

laurent's avatar
laurent committed
450 451
  AssertFatal(load_configmodule(argc,argv,0) != NULL,
	     "[SOFTMODEM] Error, configuration module init failed\n");
452
  mode = normal_txrx;
laurent's avatar
laurent committed
453

454
  logInit();
455
  get_options ();
laurent's avatar
laurent committed
456 457 458 459 460 461 462 463 464 465 466 467 468 469
  AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n");
  
    configure_linux();
    // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
  signal(SIGTERM, signal_handler);
  signal(SIGABRT, signal_handler);
  cpuf=get_cpu_freq_GHz();

  #ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "OAI Version: %s\n", PACKAGE_VERSION);
470

471
  if (is_nos1exec(argv[0]) )
472 473
    set_softmodem_optmask(SOFTMODEM_NOS1_BIT);

474
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
475

476
#if T_TRACER
477
  T_Config_Init();
478
#endif
479 480
  //randominit (0);
  set_taus_seed (0);
481

laurent's avatar
laurent committed
482
  if (opp_enabled ==1) 
483
    reset_opp_meas();
484

Cedric Roux's avatar
Cedric Roux committed
485
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
laurent's avatar
laurent committed
486
  // allows to forward in wireshark L2 protocol for decoding
487
  init_opt();
488 489

  /* Read configuration */
490
  if (RC.nb_inst > 0) {
491
    read_config_and_init();
492 493
    /* Start the agent. If it is turned off in the configuration, it won't start */
    RCconfig_flexran();
laurent's avatar
laurent committed
494 495
    
    for (i = 0; i < RC.nb_inst; i++) 
496
      flexran_agent_start(i);
laurent's avatar
laurent committed
497
    
498 499 500
    /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
     * for monolithic/F1 modes */
    init_pdcp();
laurent's avatar
laurent committed
501
    
502 503 504
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
505
    }
506 507 508

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
509
      RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
510
      itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
511
    }
frtabu's avatar
frtabu committed
512
  } else {
513
    printf("RC.nb_inst = 0, Initializing L1\n");
514
    RCconfig_L1();
515
  }
Raymond Knopp's avatar
Raymond Knopp committed
516

517
  if (RC.nb_inst > 0 && NODE_IS_CU(RC.rrc[0]->node_type)) {
518 519 520 521 522
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
523 524
    ctxt.frame = 0;
    ctxt.subframe = 0;
525 526 527
    pdcp_run(&ctxt);
  }

528
  /* start threads if only L1 or not a CU */
529
  if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
530
    // init UE_PF_PO and mutex lock
Raymond Knopp's avatar
Raymond Knopp committed
531 532 533 534 535
    pthread_mutex_init(&ue_pf_po_mutex, NULL);
    memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
    mlockall(MCL_CURRENT | MCL_FUTURE);
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
frtabu's avatar
frtabu committed
536

537

538

Raymond Knopp's avatar
Raymond Knopp committed
539
    rt_sleep_ns(10*100000000ULL);
540

frtabu's avatar
frtabu committed
541 542
    if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
      LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
543 544 545
      pthread_cond_init(&sync_cond,NULL);
      pthread_mutex_init(&sync_mutex, NULL);
    }
546

frtabu's avatar
frtabu committed
547
    if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
548
#if defined(PRE_SCD_THREAD)
549
      init_ru_vnf();  // ru pointer is necessary for pre_scd.
550
#endif
Raymond Knopp's avatar
Raymond Knopp committed
551
      wait_nfapi_init("main?");
552
    }
553

frtabu's avatar
frtabu committed
554
    LOG_I(ENB_APP,"START MAIN THREADS\n");
Raymond Knopp's avatar
Raymond Knopp committed
555
    // start the main threads
556
    number_of_cards = 1;
557
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
558

559
    if (RC.nb_L1_inst > 0) {
560 561
      printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
      init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
562
      //      for (inst=0;inst<RC.nb_L1_inst;inst++)
563
      //  for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
564
    }
565

566
    printf("wait_eNBs()\n");
567
    wait_eNBs();
568
    printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
569

570 571 572
    // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
    // but RU thread deals with pre_scd and this is necessary in VNF and simulator.
    // some initialization is necessary and init_ru_vnf do this.
frtabu's avatar
frtabu committed
573
    if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
574
      printf("Initializing RU threads\n");
575
      init_RU(get_softmodem_params()->rf_config_file);
576

frtabu's avatar
frtabu committed
577
      for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
578 579
        RC.ru[ru_id]->rf_map.card=0;
        RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
580 581
      }
    }
582

583
    config_sync_var=0;
584

frtabu's avatar
frtabu committed
585
    if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
586 587 588 589
      wait_nfapi_init("main?");
    }

    printf("wait RUs\n");
590
    // end of CI modifications
591
    wait_RUs();
frtabu's avatar
frtabu committed
592
    LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
593
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
laurent's avatar
laurent committed
594
    
frtabu's avatar
frtabu committed
595 596
    if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
597 598
      init_eNB_afterRU();
    } else {
frtabu's avatar
frtabu committed
599
      LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
600 601
    }

frtabu's avatar
frtabu committed
602
    LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
603 604
    // connect the TX/RX buffers
    sleep(1); /* wait for thread activation */
frtabu's avatar
frtabu committed
605
    LOG_I(ENB_APP,"Sending sync to all threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
606 607 608 609
    pthread_mutex_lock(&sync_mutex);
    sync_var=0;
    pthread_cond_broadcast(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
610
    config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
Raymond Knopp's avatar
Raymond Knopp committed
611
  }
612

613
  // wait for end of program
614
  LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
615 616 617 618
  // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
  fflush(stdout);
  fflush(stderr);
  // end of CI modifications
Raymond Knopp's avatar
 
Raymond Knopp committed
619
  //getchar();
620 621
  if(IS_SOFTMODEM_DOFORMS)
     load_softscope("enb");
Raymond Knopp's avatar
 
Raymond Knopp committed
622
  itti_wait_tasks_end();
623
  oai_exit=1;
624
  LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
Raymond Knopp's avatar
 
Raymond Knopp committed
625
  // stop threads
626

627
  if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
628 629
    if(IS_SOFTMODEM_DOFORMS)
      end_forms();
630

631
    LOG_I(ENB_APP,"stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
632
    stop_eNB(NB_eNB_INST);
633
    stop_RU(RC.nb_RU);
frtabu's avatar
frtabu committed
634

635 636 637 638 639 640 641
    /* release memory used by the RU/eNB threads (incomplete), after all
     * threads have been stopped (they partially use the same memory) */
    for (int inst = 0; inst < NB_eNB_INST; inst++) {
      for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) {
        phy_free_lte_eNB(RC.eNB[inst][cc_id]);
      }
    }
frtabu's avatar
frtabu committed
642

643
    for (int inst = 0; inst < RC.nb_RU; inst++) {
644 645
      phy_free_RU(RC.ru[inst]);
    }
frtabu's avatar
frtabu committed
646

647
    free_lte_top();
648
    end_configmodule();
Raymond Knopp's avatar
Raymond Knopp committed
649 650 651 652 653
    pthread_cond_destroy(&sync_cond);
    pthread_mutex_destroy(&sync_mutex);
    pthread_cond_destroy(&nfapi_sync_cond);
    pthread_mutex_destroy(&nfapi_sync_mutex);
    pthread_mutex_destroy(&ue_pf_po_mutex);
frtabu's avatar
frtabu committed
654

655
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
656 657 658 659
      if (RC.ru[ru_id]->rfdevice.trx_end_func) {
        RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
      }
frtabu's avatar
frtabu committed
660

661 662 663 664
      if (RC.ru[ru_id]->ifdevice.trx_end_func) {
        RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
      }
Raymond Knopp's avatar
Raymond Knopp committed
665
    }
Raymond Knopp's avatar
Raymond Knopp committed
666 667
  }

668
  terminate_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
669
  logClean();
670
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
671 672
  return 0;
}