lte-softmodem.c 28 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 68 69 70 71

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
72
#include "common/utils/LOG/log.h"
Navid Nikaein's avatar
Navid Nikaein committed
73
#include "UTIL/OTG/otg_tx.h"
74
#include "UTIL/OTG/otg_externs.h"
75
#include "UTIL/MATH/oml.h"
76
#include "common/utils/LOG/vcd_signal_dumper.h"
77
#include "UTIL/OPT/opt.h"
78
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
79
//#include "PHY/TOOLS/time_meas.h"
80

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

85
#if defined(ENABLE_ITTI)
86
  #include "create_tasks.h"
87 88
#endif

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

91 92
#include "system.h"

93
#ifdef XFORMS
94 95
  #include "PHY/TOOLS/lte_phy_scope.h"
  #include "stats.h"
96
#endif
97
#include "lte-softmodem.h"
oai's avatar
oai committed
98
#include "NB_IoT_interface.h"
99
#ifdef XFORMS
100 101 102 103 104 105 106 107
  // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
  // at eNB 0, an UL scope for every UE
  FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
  FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
  char title[255];
  unsigned char                   scope_enb_num_ue = 2;
  static pthread_t                forms_thread; //xforms
108 109
#endif //XFORMS

frtabu's avatar
frtabu committed
110
#ifndef ENABLE_USE_MME
111
  #define EPC_MODE_ENABLED 0
frtabu's avatar
frtabu committed
112 113
#endif

114 115 116 117 118 119
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

uint8_t nfapi_mode = 0; // Default to monolithic mode

120 121
uint16_t sf_ahead=4;

Raymond Knopp's avatar
 
Raymond Knopp committed
122 123
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
124
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
125
int config_sync_var=-1;
126

127 128
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
129

130

Raymond Knopp's avatar
Raymond Knopp committed
131
volatile int             oai_exit = 0;
132

133
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
134
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
135

136
int UE_scan = 1;
137
int UE_scan_carrier = 0;
138
runmode_t mode = normal_txrx;
Raymond Knopp's avatar
Raymond Knopp committed
139
int simL1flag;
140 141
FILE *input_fd=NULL;

142

143 144
#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
145 146
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
147 148 149 150
#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
151
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
152

153
double rx_gain_off = 0.0;
154

Raymond Knopp's avatar
 
Raymond Knopp committed
155
double sample_rate=30.72e6;
156
double bw = 10.0e6;
157

Florian Kaltenberger's avatar
Florian Kaltenberger committed
158

159 160 161
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

162 163
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
164

Raymond Knopp's avatar
 
Raymond Knopp committed
165 166 167
char ref[128] = "internal";
char channels[128] = "0";

168
int                      rx_input_level_dBm;
169

170
#ifdef XFORMS
171
  extern int                      otg_enabled;
172
#else
173
  int                             otg_enabled;
174
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
175
//int                             number_of_cards =   1;
176

177

178 179
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
180

181

182 183
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
184

185 186 187

extern void init_eNB_afterRU(void);

188
int transmission_mode=1;
189
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
190
int numerology = 0;
191

laurent's avatar
laurent committed
192
THREAD_STRUCT thread_struct;
193 194 195
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

196 197
double cpuf;

Raymond Knopp's avatar
 
Raymond Knopp committed
198 199


200 201 202
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

203 204 205 206 207
/*---------------------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 };

208
struct timespec clock_difftime(struct timespec start, struct timespec end) {
209
  struct timespec temp;
210

211 212 213 214 215 216 217
  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;
  }
218

219
  return temp;
220 221
}

wujing's avatar
wujing committed
222 223
nfapi_release_rnti_request_body_t release_rntis;

224
void print_difftimes(void) {
225
#ifdef DEBUG
226
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
227
#else
228
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
229 230 231
#endif
}

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

237 238 239 240
  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;
  }
241

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

247
#if 1
248

249
  if (changed) print_difftimes();
250

251 252 253 254 255
#endif
}

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

256
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
Raymond Knopp's avatar
 
Raymond Knopp committed
257
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
258
}
259
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
Raymond Knopp's avatar
 
Raymond Knopp committed
260
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
261 262
}

263

264
void signal_handler(int sig) {
265 266 267 268 269 270 271 272 273 274
  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);
275
  } else {
276 277
    printf("Linux signal %s...\n",strsignal(sig));
    exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n");
278 279
  }
}
Raymond Knopp's avatar
Raymond Knopp committed
280

281

282
void exit_function(const char *file, const char *function, const int line, const char *s) {
283
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
284

285
  if (s != NULL) {
286
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
287 288
  }

289
  close_log_mem();
290
  oai_exit = 1;
291

292 293
  if (RC.ru == NULL)
    exit(-1); // likely init not completed, prevent crash or hang, exit now...
294

295 296 297 298
  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;
299 300
    }

301 302 303 304 305
    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;
    }
  }
306

307 308
  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
309
}
310

311
#ifdef XFORMS
312

313

314
void reset_stats(FL_OBJECT *button, long arg) {
315
  int i,j,k;
316
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
317 318 319

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
320
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
321 322 323
        phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
324
      }
325

326 327 328
      phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
329 330 331
      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
332 333 334 335
    }
  }
}

336
static void *scope_thread(void *arg) {
337
# ifdef ENABLE_XFORMS_WRITE_STATS
338
  FILE *eNB_stats;
339
# endif
Raymond Knopp's avatar
 
Raymond Knopp committed
340
  struct sched_param sched_param;
341
  int UE_id, CC_id;
342
  int ue_cnt=0;
343
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
344 345
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
346
# ifdef ENABLE_XFORMS_WRITE_STATS
347
  eNB_stats = fopen("eNB_stats.txt", "w");
348
#endif
349

Raymond Knopp's avatar
 
Raymond Knopp committed
350
  while (!oai_exit) {
351 352 353 354 355 356 357 358 359 360 361 362
    ue_cnt=0;

    for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        if ((ue_cnt<scope_enb_num_ue)) {
          phy_scope_eNB(form_enb[CC_id][ue_cnt],
                        RC.eNB[0][CC_id],
                        UE_id);
          ue_cnt++;
        }
      }
    }
363

Florian Kaltenberger's avatar
Florian Kaltenberger committed
364
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
365
  }
366

367
  //  printf("%s",stats_buffer);
368
# ifdef ENABLE_XFORMS_WRITE_STATS
369

370 371 372 373 374
  if (eNB_stats) {
    rewind (eNB_stats);
    fwrite (stats_buffer, 1, len, eNB_stats);
    fclose (eNB_stats);
  }
375

376
# endif
377
  pthread_exit((void *)arg);
378 379 380
}
#endif

381

382
static void get_options(void) {
383
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
384
  get_common_options();
385
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
oai's avatar
oai committed
386

387
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
388 389 390 391 392 393
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    RCConfig();
    NB_eNB_INST = RC.nb_inst;
    printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);

394
    if (!IS_SOFTMODEM_NONBIOT) {
395 396 397 398 399 400 401 402
      load_NB_IoT();
      printf("               nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
             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;
    }
  }
403 404 405
}


406

407

408

409
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
410 411 412
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
413
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
414 415 416 417 418 419 420 421 422 423
    /* 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;
424
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    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;
440 441 442 443
    //    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
444
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
445
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
446 447 448
  }
}

449
void wait_RUs(void) {
450 451
  /* 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);
452 453
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
454

455 456
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
457
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
458 459
  }

460
  pthread_mutex_unlock(&RC.ru_mutex);
461 462 463
  LOG_I(PHY,"RUs configured\n");
}

464
void wait_eNBs(void) {
465 466 467 468
  int i,j;
  int waiting=1;

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

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

476 477 478 479 480
      for (j=0; j<RC.nb_L1_CC[i]; j++) {
        if (RC.eNB[i][j]->configured==0) {
          waiting=1;
          break;
        }
481 482
      }
    }
483
  }
484

485 486
  printf("eNB L1 are configured\n");
}
487

488
#if defined(ENABLE_ITTI)
489 490
/*
 * helper function to terminate a certain ITTI task
491
 */
492
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
493
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
494
        itti_get_task_name(from), from, itti_get_task_name(to), to);
495
  MessageDef *msg;
496 497
  msg = itti_alloc_new_message (from, TERMINATE_MESSAGE);
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
498 499
}

500
extern void  free_transport(PHY_VARS_eNB *);
501
extern void  phy_free_RU(RU_t *);
502

503
int stop_L1L2(module_id_t enb_id) {
504 505
  LOG_W(ENB_APP, "stopping lte-softmodem\n");

506
  if (!RC.ru) {
507
    LOG_UI(ENB_APP, "no RU configured\n");
508 509 510
    return -1;
  }

511
  /* these tasks need to pick up new configuration */
512
  terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
Robert Schmidt's avatar
Robert Schmidt committed
513
  oai_exit = 1;
514
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
Robert Schmidt's avatar
Robert Schmidt committed
515
  kill_RU_proc(RC.ru[enb_id]);
516
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
517
  kill_eNB_proc(enb_id);
518
  oai_exit = 0;
519

520 521 522 523
  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]);
  }
524

525
  phy_free_RU(RC.ru[enb_id]);
526
  free_lte_top();
527 528 529 530
  return 0;
}

/*
531
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
532
 */
533
int restart_L1L2(module_id_t enb_id) {
534 535 536
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
537 538
  LOG_W(ENB_APP, "restarting lte-softmodem\n");
  /* block threads */
539
  pthread_mutex_lock(&sync_mutex);
540
  sync_var = -1;
541
  pthread_mutex_unlock(&sync_mutex);
542

543 544
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
545 546
  }

547 548 549 550 551
  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]);
552 553 554
  /* 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);
555
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
556

557 558 559 560 561 562
  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");
  }
563

564 565 566 567 568
  /* 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);
569 570
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
571 572 573 574 575 576
  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();
577 578 579 580 581 582
  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;
583
}
584
#endif
585

586
static  void wait_nfapi_init(char *thread_name) {
587 588
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
589

590 591
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
592

593 594 595 596
  pthread_mutex_unlock(&nfapi_sync_mutex);
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

597
int main( int argc, char **argv ) {
598
  int i;
599
#if defined (XFORMS)
Raymond Knopp's avatar
 
Raymond Knopp committed
600
  void *status;
601
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
602
  int CC_id;
603
  int ru_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
604
#if defined (XFORMS)
605 606
  int ret;
#endif
607

608
  if ( load_configmodule(argc,argv,0) == NULL) {
609
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
610
  }
611

612
  mode = normal_txrx;
Raymond Knopp's avatar
 
Raymond Knopp committed
613
  set_latency_target();
614
  logInit();
615
  printf("Reading in command-line options\n");
616
  get_options ();
617

618
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
619 620
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
621
  }
Raymond Knopp's avatar
Raymond Knopp committed
622

623
#if T_TRACER
624
  T_Config_Init();
625
#endif
626 627
  //randominit (0);
  set_taus_seed (0);
628
  printf("configuring for RAU/RRU\n");
629

630
  if (opp_enabled ==1) {
631
    reset_opp_meas();
632
  }
633

634
  cpuf=get_cpu_freq_GHz();
635
#if defined(ENABLE_ITTI)
636
  printf("ITTI init, useMME: %i\n" ,EPC_MODE_ENABLED);
Cedric Roux's avatar
Cedric Roux committed
637
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
638

639
  // initialize mscgen log after ITTI
640
  if (get_softmodem_params()->start_msc) {
641
    load_module_shlib("msc",NULL,0,&msc_interface);
642
  }
643

644
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
645
#endif
646
  init_opt();
647
#ifdef PDCP_USE_NETLINK
648
  printf("PDCP netlink\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
649
  netlink_init();
650 651 652
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
653
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
654 655 656
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
657 658
  signal(SIGTERM, signal_handler);
  signal(SIGABRT, signal_handler);
Raymond Knopp's avatar
 
Raymond Knopp committed
659
  check_clock();
660 661 662 663
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
664
  printf("Runtime table\n");
665
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
laurent's avatar
laurent committed
666
#ifndef DEADLINE_SCHEDULER
667
  printf("NO deadline scheduler\n");
668
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
669 670 671 672
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
673
#ifdef CPU_AFFINITY
674

675 676 677
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
678

679
    if (s != 0) {
680 681
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
682
    }
683

684 685
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
686

687
#endif
688 689
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
690

691 692 693 694
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
695

696
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
697

698 699 700 701 702
  for (int j = 0; j < CPU_SETSIZE; j++) {
    if (CPU_ISSET(j, &cpuset)) {
      char temp[1024];
      sprintf(temp, " CPU_%d ", j);
      strcat(cpu_affinity, temp);
703
    }
704
  }
705

706
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
707
#endif
winckel's avatar
winckel committed
708
#if defined(ENABLE_ITTI)
709

710
  if (RC.nb_inst > 0)  {
Raymond Knopp's avatar
Raymond Knopp committed
711
    // don't create if node doesn't connect to RRC/S1/GTP
712 713 714 715 716
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1); // need a softer mode
    }

717
    printf("ITTI tasks created\n");
718
  } else {
719 720
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
721
  }
722

723
#endif
724
  /* Start the agent. If it is turned off in the configuration, it won't start */
725
  RCconfig_flexran();
726

727 728
  for (i = 0; i < RC.nb_L1_inst; i++) {
    flexran_agent_start(i);
729
  }
730 731 732

  // init UE_PF_PO and mutex lock
  pthread_mutex_init(&ue_pf_po_mutex, NULL);
733
  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
734
  mlockall(MCL_CURRENT | MCL_FUTURE);
Raymond Knopp's avatar
 
Raymond Knopp committed
735 736
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
737
#ifdef XFORMS
738
  int UE_id;
739 740
  printf("XFORMS\n");

741
  if (get_softmodem_params()->do_forms==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
742
    fl_initialize (&argc, argv, NULL, 0, 0);
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
    form_stats_l2 = create_form_stats_form();
    fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
    form_stats = create_form_stats_form();
    fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");

    for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        form_enb[CC_id][UE_id] = create_lte_phy_scope_enb();
        sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id);
        fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

        if (otg_enabled) {
          fl_set_button(form_enb[CC_id][UE_id]->button_0,1);
          fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON");
        } else {
          fl_set_button(form_enb[CC_id][UE_id]->button_0,0);
          fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF");
        }
      } // CC_id
    } // UE_id

Raymond Knopp's avatar
 
Raymond Knopp committed
764
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
765

766 767
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
768

Raymond Knopp's avatar
 
Raymond Knopp committed
769 770
    printf("Scope thread created, ret=%d\n",ret);
  }
771

772
#endif
773
  rt_sleep_ns(10*100000000ULL);
Cedric Roux's avatar
Cedric Roux committed
774

775
  if (nfapi_mode) {
776 777 778 779 780
    printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
  }

781 782 783 784 785 786
  const char *nfapi_mode_str = "<UNKNOWN>";

  switch(nfapi_mode) {
    case 0:
      nfapi_mode_str = "MONOLITHIC";
      break;
787

788 789 790
    case 1:
      nfapi_mode_str = "PNF";
      break;
791

792 793 794
    case 2:
      nfapi_mode_str = "VNF";
      break;
795

796 797 798 799
    default:
      nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
      break;
  }
800

801 802
  printf("NFAPI MODE:%s\n", nfapi_mode_str);

803 804 805 806 807

if (nfapi_mode==2) {// VNF
#if defined(PRE_SCD_THREAD)
    init_ru_vnf();  // ru pointer is necessary for pre_scd.
#endif
808
    wait_nfapi_init("main?");
809 810
  }

811 812

  printf("START MAIN THREADS\n");
813
  // start the main threads
814 815 816 817 818 819 820 821 822
  number_of_cards = 1;
  printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);

  if (RC.nb_L1_inst > 0) {
    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);
    //      for (inst=0;inst<RC.nb_L1_inst;inst++)
    //  for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
  }
823

824 825
  printf("wait_eNBs()\n");
  wait_eNBs();
826

827
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
828

wujing's avatar
wujing committed
829 830 831 832
  // 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 != 2) {
833 834
    printf("Initializing RU threads\n");
    init_RU(get_softmodem_params()->rf_config_file);
wujing's avatar
wujing committed
835 836 837
    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);
838
    }
839
  }
840

841
  config_sync_var=0;
842

843 844 845
  if (nfapi_mode==1) { // PNF
    wait_nfapi_init("main?");
  }
846

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
  printf("wait RUs\n");
  fflush(stdout);
  fflush(stderr);
  wait_RUs();
  printf("ALL RUs READY!\n");
  printf("RC.nb_RU:%d\n", RC.nb_RU);
  // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
  printf("ALL RUs ready - init eNBs\n");

  if (nfapi_mode != 1 && nfapi_mode != 2) {
    printf("Not NFAPI mode - call init_eNB_afterRU()\n");
    init_eNB_afterRU();
  } else {
    printf("NFAPI mode - DO NOT call init_eNB_afterRU()\n");
  }
862

863
  printf("ALL RUs ready - ALL eNBs ready\n");
864
  // connect the TX/RX buffers
865
  sleep(1); /* wait for thread activation */
866
  printf("Sending sync to all threads\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
867
  pthread_mutex_lock(&sync_mutex);
868
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
869 870
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
871
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
872
  // wait for end of program
Raymond Knopp's avatar
 
Raymond Knopp committed
873 874
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
875
#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
876 877
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
878
  printf("Returned from ITTI signal handler\n");
879
  oai_exit=1;
880
  printf("oai_exit=%d\n",oai_exit);
881
#else
882

Raymond Knopp's avatar
 
Raymond Knopp committed
883
  while (oai_exit==0)
884
    rt_sleep_ns(100000000ULL);
885

886
  printf("Terminating application - oai_exit=%d\n",oai_exit);
887
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
888
  // stop threads
889
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
890
  printf("waiting for XFORMS thread\n");
891

892
  if (get_softmodem_params()->do_forms==1) {
893 894 895
    pthread_join(forms_thread,&status);
    fl_hide_form(form_stats->stats_form);
    fl_free_form(form_stats->stats_form);
896 897
    fl_hide_form(form_stats_l2->stats_form);
    fl_free_form(form_stats_l2->stats_form);
898

899 900 901 902
    for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
        fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
Raymond Knopp's avatar
 
Raymond Knopp committed
903
      }
904
    }
905 906
  }

907
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
908
  printf("stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
909 910
  stop_eNB(NB_eNB_INST);
  stop_RU(RC.nb_RU);
911

Robert Schmidt's avatar
Robert Schmidt committed
912 913 914 915 916 917
  /* 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++) {
      free_transport(RC.eNB[inst][cc_id]);
      phy_free_lte_eNB(RC.eNB[inst][cc_id]);
918
    }
Robert Schmidt's avatar
Robert Schmidt committed
919
  }
920

Robert Schmidt's avatar
Robert Schmidt committed
921 922 923
  for (int inst = 0; inst < RC.nb_RU; inst++) {
    phy_free_RU(RC.ru[inst]);
  }
924

925
  free_lte_top();
926
  end_configmodule();
Raymond Knopp's avatar
 
Raymond Knopp committed
927 928
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
929 930
  pthread_cond_destroy(&nfapi_sync_cond);
  pthread_mutex_destroy(&nfapi_sync_mutex);
931
  pthread_mutex_destroy(&ue_pf_po_mutex);
932

933 934 935 936 937
  for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
    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;
    }
938

939 940 941
    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
942
    }
943 944
  }

945
  terminate_opt();
946
  logClean();
947
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
948 949
  return 0;
}