lte-softmodem.c 24.7 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
laurent's avatar
laurent committed
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
#include "lte-softmodem.h"
oai's avatar
oai committed
95
#include "NB_IoT_interface.h"
laurent's avatar
laurent committed
96
#include <executables/split_headers.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

laurent's avatar
laurent committed
111 112 113 114
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]


Raymond Knopp's avatar
Raymond Knopp committed
115
volatile int             oai_exit = 0;
116

117
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
118
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
119

120
int UE_scan = 1;
121
int UE_scan_carrier = 0;
122
runmode_t mode = normal_txrx;
frtabu's avatar
frtabu committed
123

124 125
FILE *input_fd=NULL;

126

127
#if MAX_NUM_CCs == 1
128
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
129 130
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
131 132 133 134
#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
135
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
136

137
double rx_gain_off = 0.0;
138

Raymond Knopp's avatar
 
Raymond Knopp committed
139
double sample_rate=30.72e6;
140
double bw = 10.0e6;
141

142 143 144
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

145 146
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
147

Raymond Knopp's avatar
 
Raymond Knopp committed
148 149 150
char ref[128] = "internal";
char channels[128] = "0";

laurent's avatar
laurent committed
151
int rx_input_level_dBm;
152
int otg_enabled;
laurent's avatar
laurent committed
153

154
uint64_t num_missed_slots=0; // counter for the number of missed slots
155

laurent's avatar
laurent committed
156 157 158 159 160 161 162
int split73=0;
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) {
  AssertFatal(false, "Must not be called in this context\n");
}
void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) {
  AssertFatal(false, "Must not be called in this context\n");
}
laurent's avatar
laurent committed
163 164 165 166 167

extern void reset_opp_meas(void);
extern void print_opp_meas(void);


168 169
extern void init_eNB_afterRU(void);

170
int transmission_mode=1;
171
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
172
int numerology = 0;
173
int usrp_tx_thread = 0;
174

laurent's avatar
laurent committed
175
THREAD_STRUCT thread_struct;
176 177
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;
laurent's avatar
laurent committed
178

179 180
double cpuf;

181
int oaisim_flag=0;
182

laurent's avatar
laurent committed
183

184 185 186
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

laurent's avatar
laurent committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end) {
  struct timespec temp;

  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }

  return temp;
}

void print_difftimes(void) {
#ifdef DEBUG
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end) {
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);

  if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
    min_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }

  if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
    max_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }

#if 1

  if (changed) print_difftimes();

#endif
}

/*------------------------------------------------------------------------*/

unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}


246
void exit_function(const char *file, const char *function, const int line, const char *s) {
247
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
248

249
  if (s != NULL) {
250
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
251
  }
252
  close_log_mem();
253
  oai_exit = 1;
254

255 256
  if (RC.ru == NULL)
    exit(-1); // likely init not completed, prevent crash or hang, exit now...
257

258 259 260 261
  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;
262 263
    }

264 265 266 267 268
    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;
    }
  }
269

270 271
  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
272
}
273

laurent's avatar
laurent committed
274

275
static void get_options(void) {
276
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
277
  get_common_options(SOFTMODEM_ENB_BIT );
278
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
oai's avatar
oai committed
279

280
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
281 282 283 284
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    RCConfig();
    NB_eNB_INST = RC.nb_inst;
laurent's avatar
laurent committed
285
    printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
286

287
    if (!IS_SOFTMODEM_NONBIOT) {
288
      load_NB_IoT();
laurent's avatar
laurent committed
289
      printf("               nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
290 291 292 293 294 295
             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;
    }
  }
296 297
}

laurent's avatar
laurent committed
298 299 300 301




302
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
303 304 305
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
306
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
307 308 309 310 311 312 313 314 315 316
    /* 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;
317
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
    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;
333 334 335 336
    //    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
337
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
338
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
339 340 341
  }
}

342
void wait_RUs(void) {
343 344
  /* 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);
345 346
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
347

348 349
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
350
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
351 352
  }

353
  pthread_mutex_unlock(&RC.ru_mutex);
354 355 356
  LOG_I(PHY,"RUs configured\n");
}

357
void wait_eNBs(void) {
358 359 360 361
  int i,j;
  int waiting=1;

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

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

369 370 371 372 373
      for (j=0; j<RC.nb_L1_CC[i]; j++) {
        if (RC.eNB[i][j]->configured==0) {
          waiting=1;
          break;
        }
374 375
      }
    }
376
  }
377

378 379
  printf("eNB L1 are configured\n");
}
380

381

382 383
/*
 * helper function to terminate a certain ITTI task
384
 */
385
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
386
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
387
        itti_get_task_name(from), from, itti_get_task_name(to), to);
388
  MessageDef *msg;
389
  msg = itti_alloc_new_message (from, 0, TERMINATE_MESSAGE);
390
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
391 392
}

393
extern void  free_transport(PHY_VARS_eNB *);
394
extern void  phy_free_RU(RU_t *);
395

396
int stop_L1L2(module_id_t enb_id) {
397 398
  LOG_W(ENB_APP, "stopping lte-softmodem\n");

399
  if (!RC.ru) {
400
    LOG_UI(ENB_APP, "no RU configured\n");
401 402 403
    return -1;
  }

404
  /* these tasks need to pick up new configuration */
405
  terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
Robert Schmidt's avatar
Robert Schmidt committed
406
  oai_exit = 1;
407
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
Robert Schmidt's avatar
Robert Schmidt committed
408
  kill_RU_proc(RC.ru[enb_id]);
409
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
410
  kill_eNB_proc(enb_id);
411
  oai_exit = 0;
412

413 414 415 416
  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]);
  }
417

418
  phy_free_RU(RC.ru[enb_id]);
419
  free_lte_top();
420 421 422 423
  return 0;
}

/*
424
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
425
 */
426
int restart_L1L2(module_id_t enb_id) {
427 428 429
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
430 431
  LOG_W(ENB_APP, "restarting lte-softmodem\n");
  /* block threads */
432
  pthread_mutex_lock(&sync_mutex);
433
  sync_var = -1;
434
  pthread_mutex_unlock(&sync_mutex);
435

436 437
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
438 439
  }

440 441
  RC.ru_mask |= (1 << ru->idx);
  set_function_spec_param(RC.ru[enb_id]);
442 443
  /* reset the list of connected UEs in the MAC, since in this process with
   * loose all UEs (have to reconnect) */
444
  init_UE_info(&RC.mac[enb_id]->UE_info);
445
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
446

447 448 449 450 451 452
  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");
  }
453

454 455
  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
456
  msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
457 458
  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);
459 460
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
461 462 463 464 465 466
  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();
467 468 469 470 471 472
  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;
473
}
474

475 476 477 478
void init_pdcp(void) {
  if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
    pdcp_layer_init();
    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
479 480
                             (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;

481 482
    if (IS_SOFTMODEM_NOS1)
      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
483

484 485
    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;

laurent's avatar
laurent committed
486
    pdcp_module_init(pdcp_initmask);
487 488

    if (NODE_IS_CU(RC.rrc[0]->node_type)) {
489
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
490
    } else {
491 492
      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);
493 494
    }
  } else {
495
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
496 497
  }
}
498

499
static  void wait_nfapi_init(char *thread_name) {
500 501
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
502

503 504
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
505

506
  pthread_mutex_unlock(&nfapi_sync_mutex);
507
  printf( "NFAPI: got sync (%s)\n", thread_name);
508 509
}

yilmazt's avatar
yilmazt committed
510 511
int main ( int argc, char **argv )
{
512
  int i;
513
  int CC_id = 0;
514
  int ru_id;
515
  int node_type = ngran_eNB;
516

laurent's avatar
laurent committed
517 518 519 520
  if ( load_configmodule(argc,argv,0) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }

521
  mode = normal_txrx;
laurent's avatar
laurent committed
522
  set_latency_target();
523
  logInit();
laurent's avatar
laurent committed
524
  printf("Reading in command-line options\n");
525
  get_options ();
526

527
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
528

laurent's avatar
laurent committed
529 530 531 532 533
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
  }

534
#if T_TRACER
535
  T_Config_Init();
536
#endif
537 538
  //randominit (0);
  set_taus_seed (0);
laurent's avatar
laurent committed
539
  printf("configuring for RAU/RRU\n");
540

laurent's avatar
laurent committed
541
  if (opp_enabled ==1) {
542
    reset_opp_meas();
laurent's avatar
laurent committed
543
  }
544

laurent's avatar
laurent committed
545 546
  cpuf=get_cpu_freq_GHz();
  printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
Laurent Thomas's avatar
Laurent Thomas committed
547
  itti_init(TASK_MAX, tasks_info);
laurent's avatar
laurent committed
548
  // allows to forward in wireshark L2 protocol for decoding
laurent's avatar
laurent committed
549 550 551 552 553
  // initialize mscgen log after ITTI
  if (get_softmodem_params()->start_msc) {
    load_module_shlib("msc",NULL,0,&msc_interface);
  }

554
  MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX);
555
  init_opt();
556 557
  // to make a graceful exit when ctrl-c is pressed
  set_softmodem_sighandler();
laurent's avatar
laurent committed
558 559 560 561 562 563 564 565
  check_clock();
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
  printf("Runtime table\n");
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);

566
  /* Read configuration */
567
  if (RC.nb_inst > 0) {
568
    read_config_and_init();
569 570 571 572 573 574 575 576 577 578 579 580 581
  } else {
    printf("RC.nb_inst = 0, Initializing L1\n");
    RCconfig_L1();
  }

  /* We need to read RU configuration before FlexRAN starts so it knows what
   * splits to report. Actual RU start comes later. */
  if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) {
    RCconfig_RU();
    LOG_I(PHY,
          "number of L1 instances %d, number of RU %d, number of CPU cores %d\n",
          RC.nb_L1_inst, RC.nb_RU, get_nprocs());
  }
582

583
  if (RC.nb_inst > 0) {
584
    /* Start the agent. If it is turned off in the configuration, it won't start */
laurent's avatar
laurent committed
585
    for (i = 0; i < RC.nb_inst; i++) {
586
      flexran_agent_start(i);
laurent's avatar
laurent committed
587
    }
laurent's avatar
laurent committed
588
    
589 590
    /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
     * for monolithic/F1 modes */
591
   init_pdcp();
laurent's avatar
laurent committed
592
    
593 594 595
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
596
    }
597 598

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
599
      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
laurent's avatar
laurent committed
600 601
      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);
602
    }
603
    node_type = RC.rrc[0]->node_type;
604
  }
Raymond Knopp's avatar
Raymond Knopp committed
605

606
  if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
607 608 609 610 611
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
612 613
    ctxt.frame = 0;
    ctxt.subframe = 0;
614 615
    pdcp_run(&ctxt);
  }
laurent's avatar
laurent committed
616

617
  /* start threads if only L1 or not a CU */
618
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
619
    // init UE_PF_PO and mutex lock
Raymond Knopp's avatar
Raymond Knopp committed
620 621
    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);
laurent's avatar
laurent committed
622
    mlockall(MCL_CURRENT | MCL_FUTURE);
Raymond Knopp's avatar
Raymond Knopp committed
623 624
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
frtabu's avatar
frtabu committed
625

Raymond Knopp's avatar
Raymond Knopp committed
626
    rt_sleep_ns(10*100000000ULL);
laurent's avatar
laurent committed
627

frtabu's avatar
frtabu committed
628 629
    if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
      LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
630 631 632
      pthread_cond_init(&sync_cond,NULL);
      pthread_mutex_init(&sync_mutex, NULL);
    }
laurent's avatar
laurent committed
633

frtabu's avatar
frtabu committed
634
    if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
635
#if defined(PRE_SCD_THREAD)
636
      init_ru_vnf();  // ru pointer is necessary for pre_scd.
637
#endif
Raymond Knopp's avatar
Raymond Knopp committed
638
      wait_nfapi_init("main?");
639
    }
laurent's avatar
laurent committed
640

frtabu's avatar
frtabu committed
641
    LOG_I(ENB_APP,"START MAIN THREADS\n");
Raymond Knopp's avatar
Raymond Knopp committed
642
    // start the main threads
643
    number_of_cards = 1;
644
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
laurent's avatar
laurent committed
645

646
    if (RC.nb_L1_inst > 0) {
647 648
      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);
Raymond Knopp's avatar
 
Raymond Knopp committed
649
    }
650 651 652
    for (int x=0; x < RC.nb_L1_inst; x++) 
      for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) {
        L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc;
laurent's avatar
laurent committed
653 654 655
	L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t));
        L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
        L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
656
        if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 )
laurent's avatar
laurent committed
657
         initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true);
658
        else
laurent's avatar
laurent committed
659 660 661
         initTpool("n", L1proc->threadPool, true);
      initNotifiedFIFO(L1proc->respEncode);
      initNotifiedFIFO(L1proc->respDecode);
662
      RC.eNB[x][CC_id]->proc.L1_proc_tx.threadPool = L1proc->threadPool;
663 664 665
    }


laurent's avatar
laurent committed
666
  }
laurent's avatar
laurent committed
667

laurent's avatar
laurent committed
668 669 670
  printf("wait_eNBs()\n");
  wait_eNBs();
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
671 672 673 674 675 676
  
  // 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.
  if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
    printf("Initializing RU threads\n");
677
    init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
678
    
679 680 681
    for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
      RC.ru[ru_id]->rf_map.card=0;
      RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
682
    }
laurent's avatar
laurent committed
683

684
    config_sync_var=0;
laurent's avatar
laurent committed
685

frtabu's avatar
frtabu committed
686
    if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
687 688
      wait_nfapi_init("main?");
    }
laurent's avatar
laurent committed
689

690
    printf("wait RUs\n");
691
    // end of CI modifications
laurent's avatar
laurent committed
692 693
    fflush(stdout);
    fflush(stderr);
laurent's avatar
laurent committed
694
    // wait_RUs() is wrong and over complex!
695
    wait_RUs();
frtabu's avatar
frtabu committed
696
    LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
697
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
laurent's avatar
laurent committed
698
    printf("ALL RUs ready - init eNBs\n");
laurent's avatar
laurent committed
699
    
frtabu's avatar
frtabu committed
700 701
    if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
702 703
      init_eNB_afterRU();
    } else {
frtabu's avatar
frtabu committed
704
      LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
705 706
    }

frtabu's avatar
frtabu committed
707
    LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
708 709
    // connect the TX/RX buffers
    sleep(1); /* wait for thread activation */
frtabu's avatar
frtabu committed
710
    LOG_I(ENB_APP,"Sending sync to all threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
711 712 713 714
    pthread_mutex_lock(&sync_mutex);
    sync_var=0;
    pthread_cond_broadcast(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
715
    create_tasks_mbms(1);
716
    config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
Raymond Knopp's avatar
Raymond Knopp committed
717
  }
718 719 720
  else
    create_tasks_mbms(1);
  //create_tasks_mbms(1);
721

722
  // wait for end of program
723
  LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
724 725 726 727
  // 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
728
  //getchar();
729
  if(IS_SOFTMODEM_DOFORMS)
730
     load_softscope("enb",NULL);
Raymond Knopp's avatar
 
Raymond Knopp committed
731
  itti_wait_tasks_end();
732
  oai_exit=1;
733
  LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
Raymond Knopp's avatar
 
Raymond Knopp committed
734
  // stop threads
735

736
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
737 738
    if(IS_SOFTMODEM_DOFORMS)
      end_forms();
739

740
    LOG_I(ENB_APP,"stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
741
    stop_eNB(NB_eNB_INST);
742
    stop_RU(RC.nb_RU);
frtabu's avatar
frtabu committed
743

744 745 746 747
    /* 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++) {
laurent's avatar
laurent committed
748
	free_transport(RC.eNB[inst][cc_id]);
749 750 751
        phy_free_lte_eNB(RC.eNB[inst][cc_id]);
      }
    }
frtabu's avatar
frtabu committed
752

753
    for (int inst = 0; inst < RC.nb_RU; inst++) {
754 755
      phy_free_RU(RC.ru[inst]);
    }
frtabu's avatar
frtabu committed
756

757
    free_lte_top();
758
    end_configmodule();
Raymond Knopp's avatar
Raymond Knopp committed
759 760 761 762 763
    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
764

765
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
766
      if (RC.ru[ru_id]->rfdevice.trx_end_func) {
laurent's avatar
laurent committed
767 768
        RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
769
      }
frtabu's avatar
frtabu committed
770

771
      if (RC.ru[ru_id]->ifdevice.trx_end_func) {
laurent's avatar
laurent committed
772 773
        RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
774
      }
Raymond Knopp's avatar
Raymond Knopp committed
775
    }
Raymond Knopp's avatar
Raymond Knopp committed
776
  }
laurent's avatar
laurent committed
777

778
  terminate_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
779
  logClean();
780
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
781 782
  return 0;
}