lte-softmodem.c 25.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
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

98 99 100
#if USING_GPROF
#  include "sys/gmon.h"
#endif
frtabu's avatar
frtabu committed
101

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

106 107
uint16_t sf_ahead=4;

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

laurent's avatar
laurent committed
113 114 115 116
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
117
volatile int             oai_exit = 0;
118

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

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

126 127
FILE *input_fd=NULL;

128

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

139
double rx_gain_off = 0.0;
140

Raymond Knopp's avatar
 
Raymond Knopp committed
141
double sample_rate=30.72e6;
142
double bw = 10.0e6;
143

144 145 146
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

147 148
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
149

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

laurent's avatar
laurent committed
153
int rx_input_level_dBm;
154
int otg_enabled;
laurent's avatar
laurent committed
155

156
uint64_t num_missed_slots=0; // counter for the number of missed slots
157

laurent's avatar
laurent committed
158 159 160 161 162 163 164
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
165 166 167 168 169

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


170 171
extern void init_eNB_afterRU(void);

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

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

180 181
double cpuf;

182
int oaisim_flag=0;
183
uint16_t ue_idx_standalone = 0xFFFF;
184

laurent's avatar
laurent committed
185

186 187 188
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

laurent's avatar
laurent committed
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 246 247
/*---------------------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));
}


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

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

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

260 261 262 263
  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;
264 265
    }

266 267 268 269 270
    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;
    }
  }
271

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

laurent's avatar
laurent committed
276

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

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

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

laurent's avatar
laurent committed
300 301 302 303




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

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

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

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

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

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

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

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

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

380 381
  printf("eNB L1 are configured\n");
}
382

383

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

395
extern void  free_transport(PHY_VARS_eNB *);
396
extern void  phy_free_RU(RU_t *);
397

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

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

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

415 416 417 418
  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]);
  }
419

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

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

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

442 443 444 445 446
  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]);
447 448
  /* reset the list of connected UEs in the MAC, since in this process with
   * loose all UEs (have to reconnect) */
449
  init_UE_info(&RC.mac[enb_id]->UE_info);
450
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
451

452 453 454 455 456 457
  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");
  }
458

459 460 461 462 463
  /* 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);
464 465
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
466 467 468 469 470 471
  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();
472 473 474 475 476 477
  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;
478
}
479

480 481 482 483
void init_pdcp(void) {
  if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
    pdcp_layer_init();
    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
484 485
                             (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;

486 487
    if (IS_SOFTMODEM_NOS1)
      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
488

489 490
    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;

491
    pdcp_module_init(pdcp_initmask, 0);
492 493

    if (NODE_IS_CU(RC.rrc[0]->node_type)) {
494
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
495
    } else {
496 497
      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);
498 499
    }
  } else {
500
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
501 502
  }
}
503

504
static  void wait_nfapi_init(char *thread_name) {
505 506
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
507

508 509
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
510

511
  pthread_mutex_unlock(&nfapi_sync_mutex);
512
  printf( "NFAPI: got sync (%s)\n", thread_name);
513 514
}

yilmazt's avatar
yilmazt committed
515 516
int main ( int argc, char **argv )
{
Michael Cook's avatar
Michael Cook committed
517 518
  struct sched_param param =
  {
Michael Cook's avatar
Michael Cook committed
519
    .sched_priority = 79
Michael Cook's avatar
Michael Cook committed
520 521
  };
  if (sched_setscheduler( 0, SCHED_RR, &param ) == -1 )
Michael Cook's avatar
Michael Cook committed
522
  {
523 524 525 526 527 528
    fprintf(stderr, "sched_setscheduler: %s\n", strerror(errno));
    return EXIT_FAILURE;
  }
  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
  {
    fprintf(stderr, "mlockall: %s\n", strerror(errno));
Michael Cook's avatar
Michael Cook committed
529
    return EXIT_FAILURE;
Michael Cook's avatar
Michael Cook committed
530
  }
Michael Cook's avatar
Michael Cook committed
531

532
  int i;
533
  int CC_id = 0;
534
  int ru_id;
535
  int node_type = ngran_eNB;
536

laurent's avatar
laurent committed
537 538 539 540
  if ( load_configmodule(argc,argv,0) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }

541
  mode = normal_txrx;
laurent's avatar
laurent committed
542
  set_latency_target();
543
  logInit();
laurent's avatar
laurent committed
544
  printf("Reading in command-line options\n");
545
  get_options ();
546

547
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
548

laurent's avatar
laurent committed
549 550 551 552 553
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
  }

554
#if T_TRACER
555
  T_Config_Init();
556
#endif
557 558
  //randominit (0);
  set_taus_seed (0);
laurent's avatar
laurent committed
559
  printf("configuring for RAU/RRU\n");
560

laurent's avatar
laurent committed
561
  if (opp_enabled ==1) {
562
    reset_opp_meas();
laurent's avatar
laurent committed
563
  }
564

laurent's avatar
laurent committed
565 566
  cpuf=get_cpu_freq_GHz();
  printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
Cedric Roux's avatar
Cedric Roux committed
567
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
laurent's avatar
laurent committed
568
  // allows to forward in wireshark L2 protocol for decoding
laurent's avatar
laurent committed
569 570 571 572 573 574
  // initialize mscgen log after ITTI
  if (get_softmodem_params()->start_msc) {
    load_module_shlib("msc",NULL,0,&msc_interface);
  }

  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
575
  init_opt();
laurent's avatar
laurent committed
576 577 578 579 580 581 582 583
  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);

584
  /* Read configuration */
585
  if (RC.nb_inst > 0) {
586
    read_config_and_init();
587 588 589 590 591 592 593 594 595 596 597 598 599
  } 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());
  }
600

601
  if (RC.nb_inst > 0) {
602
    /* Start the agent. If it is turned off in the configuration, it won't start */
laurent's avatar
laurent committed
603
    for (i = 0; i < RC.nb_inst; i++) {
604
      flexran_agent_start(i);
laurent's avatar
laurent committed
605
    }
laurent's avatar
laurent committed
606
    
607 608
    /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
     * for monolithic/F1 modes */
609
   init_pdcp();
laurent's avatar
laurent committed
610
    
611 612 613
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
614
    }
615 616

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
laurent's avatar
laurent committed
617 618 619
      MessageDef *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);
620
    }
621
    node_type = RC.rrc[0]->node_type;
622
  }
Raymond Knopp's avatar
Raymond Knopp committed
623

624
  if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
625 626 627 628 629
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
630 631
    ctxt.frame = 0;
    ctxt.subframe = 0;
632 633
    pdcp_run(&ctxt);
  }
laurent's avatar
laurent committed
634

635
  /* start threads if only L1 or not a CU */
636
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
637
    // init UE_PF_PO and mutex lock
Raymond Knopp's avatar
Raymond Knopp committed
638 639
    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
640
    mlockall(MCL_CURRENT | MCL_FUTURE);
Raymond Knopp's avatar
Raymond Knopp committed
641 642
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
frtabu's avatar
frtabu committed
643

Raymond Knopp's avatar
Raymond Knopp committed
644
    rt_sleep_ns(10*100000000ULL);
laurent's avatar
laurent committed
645

frtabu's avatar
frtabu committed
646 647
    if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
      LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
648 649 650
      pthread_cond_init(&sync_cond,NULL);
      pthread_mutex_init(&sync_mutex, NULL);
    }
laurent's avatar
laurent committed
651

frtabu's avatar
frtabu committed
652
    if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
653
#if defined(PRE_SCD_THREAD)
654
      init_ru_vnf();  // ru pointer is necessary for pre_scd.
655
#endif
Raymond Knopp's avatar
Raymond Knopp committed
656
      wait_nfapi_init("main?");
657
    }
laurent's avatar
laurent committed
658

frtabu's avatar
frtabu committed
659
    LOG_I(ENB_APP,"START MAIN THREADS\n");
Raymond Knopp's avatar
Raymond Knopp committed
660
    // start the main threads
661
    number_of_cards = 1;
662
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
laurent's avatar
laurent committed
663

664
    if (RC.nb_L1_inst > 0) {
665 666
      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
667
    }
668 669 670
    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
671 672 673
	L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t));
        L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
        L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
674
        if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 )
laurent's avatar
laurent committed
675
         initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true);
676
        else
laurent's avatar
laurent committed
677 678 679
         initTpool("n", L1proc->threadPool, true);
      initNotifiedFIFO(L1proc->respEncode);
      initNotifiedFIFO(L1proc->respDecode);
680 681 682
    }


laurent's avatar
laurent committed
683
  }
laurent's avatar
laurent committed
684

laurent's avatar
laurent committed
685 686 687
  printf("wait_eNBs()\n");
  wait_eNBs();
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
688 689 690 691 692 693
  
  // 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");
694
    init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
695
    
696 697 698
    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);
699
    }
laurent's avatar
laurent committed
700

701
    config_sync_var=0;
laurent's avatar
laurent committed
702

frtabu's avatar
frtabu committed
703
    if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
704 705
      wait_nfapi_init("main?");
    }
laurent's avatar
laurent committed
706

707
    printf("wait RUs\n");
708
    // end of CI modifications
laurent's avatar
laurent committed
709 710
    fflush(stdout);
    fflush(stderr);
laurent's avatar
laurent committed
711
    // wait_RUs() is wrong and over complex!
712
    wait_RUs();
frtabu's avatar
frtabu committed
713
    LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
714
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
laurent's avatar
laurent committed
715
    printf("ALL RUs ready - init eNBs\n");
laurent's avatar
laurent committed
716
    
frtabu's avatar
frtabu committed
717 718
    if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
719 720
      init_eNB_afterRU();
    } else {
frtabu's avatar
frtabu committed
721
      LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
722 723
    }

frtabu's avatar
frtabu committed
724
    LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
725 726
    // connect the TX/RX buffers
    sleep(1); /* wait for thread activation */
frtabu's avatar
frtabu committed
727
    LOG_I(ENB_APP,"Sending sync to all threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
728 729 730 731
    pthread_mutex_lock(&sync_mutex);
    sync_var=0;
    pthread_cond_broadcast(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
732
    config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
Raymond Knopp's avatar
Raymond Knopp committed
733
  }
734
  log_scheduler("eNB-main");
735 736
  create_tasks_mbms(1);

737
  // wait for end of program
738
  LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
739 740 741 742
  // 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
743
  //getchar();
744 745
  if(IS_SOFTMODEM_DOFORMS)
     load_softscope("enb");
Raymond Knopp's avatar
 
Raymond Knopp committed
746
  itti_wait_tasks_end();
747 748 749 750 751 752 753 754

#if USING_GPROF
  // Save the gprof data now (rather than via atexit) in case we crash while shutting down
  fprintf(stderr, "Recording gprof data...\n");
  _mcleanup();
  fprintf(stderr, "Recording gprof data...done\n");
#endif // USING_GPROF

755
  oai_exit=1;
756
  LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
Raymond Knopp's avatar
 
Raymond Knopp committed
757
  // stop threads
758

759
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
760 761
    if(IS_SOFTMODEM_DOFORMS)
      end_forms();
762

763
    LOG_I(ENB_APP,"stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
764
    stop_eNB(NB_eNB_INST);
765
    stop_RU(RC.nb_RU);
frtabu's avatar
frtabu committed
766

767 768 769 770
    /* 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
771
	free_transport(RC.eNB[inst][cc_id]);
772 773 774
        phy_free_lte_eNB(RC.eNB[inst][cc_id]);
      }
    }
frtabu's avatar
frtabu committed
775

776
    for (int inst = 0; inst < RC.nb_RU; inst++) {
777 778
      phy_free_RU(RC.ru[inst]);
    }
frtabu's avatar
frtabu committed
779

780
    free_lte_top();
781
    end_configmodule();
Raymond Knopp's avatar
Raymond Knopp committed
782 783 784 785 786
    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
787

788
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
789
      if (RC.ru[ru_id]->rfdevice.trx_end_func) {
laurent's avatar
laurent committed
790 791
        RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
792
      }
frtabu's avatar
frtabu committed
793

794
      if (RC.ru[ru_id]->ifdevice.trx_end_func) {
laurent's avatar
laurent committed
795 796
        RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
797
      }
Raymond Knopp's avatar
Raymond Knopp committed
798
    }
Raymond Knopp's avatar
Raymond Knopp committed
799
  }
laurent's avatar
laurent committed
800

801
  terminate_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
802
  logClean();
803
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
804 805
  return 0;
}