lte-softmodem.c 37.3 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 23
/*! \file lte-enb.c
 * \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 82 83 84
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

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

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

92 93
#include "system.h"

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

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

115 116 117 118 119 120
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

121 122
uint16_t sf_ahead=4;

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

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

131
#if defined(ENABLE_ITTI)
132 133
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
134
#endif
Raymond Knopp's avatar
Raymond Knopp committed
135
volatile int             oai_exit = 0;
136

137
clock_source_t clock_source = internal;
138
static int wait_for_sync = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
139

140
unsigned int                    mmapped_dma=0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
141
int                             single_thread_flag = 0;
142

143
static int8_t                     threequarter_fs=0;
144

145
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
146
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
147

148

149 150
// This is a dummy declaration (dlsch_demodulation.c is no longer compiled for eNodeB)
int16_t dlsch_demod_shift = 0;
151

152
int UE_scan = 1;
153
int UE_scan_carrier = 0;
154
runmode_t mode = normal_txrx;
Raymond Knopp's avatar
Raymond Knopp committed
155 156
int simL1flag;
int snr_dB;
157 158
FILE *input_fd=NULL;

159

160 161
#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
162 163
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
164 165 166 167
#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
168
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
169

170
double rx_gain_off = 0.0;
171

Raymond Knopp's avatar
 
Raymond Knopp committed
172
double sample_rate=30.72e6;
173
double bw = 10.0e6;
174

175
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
176

177 178
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
179
int chain_offset=0;
180
int phy_test = 0;
181
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
182

183 184 185
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

186 187
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
188

Raymond Knopp's avatar
 
Raymond Knopp committed
189 190 191
char ref[128] = "internal";
char channels[128] = "0";

192
int                      rx_input_level_dBm;
193

194
#ifdef XFORMS
195
extern int                      otg_enabled;
196
static char                     do_forms=0;
197
#else
198
int                             otg_enabled;
199
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
200
//int                             number_of_cards =   1;
201

202 203

static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
204
uint32_t target_dl_mcs = 28; //maximum allowed mcs
205
uint32_t target_ul_mcs = 20;
206
uint32_t timing_advance = 0;
207 208
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
209

210

211 212
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
213

214 215 216 217 218 219
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag);

extern void init_eNB_afterRU(void);

220
int transmission_mode=1;
221
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
222
int numerology = 0;
223 224
int codingw = 0;
int fepw = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
225

226

227

228 229 230
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

231 232 233 234
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

235 236
extern char uecap_xer[1024];
char uecap_xer_in=0;
237

238
int oaisim_flag=0;
239
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
Raymond Knopp's avatar
 
Raymond Knopp committed
240

Cedric Roux's avatar
Cedric Roux committed
241 242 243 244
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
245

246 247 248
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

249 250 251 252 253
/*---------------------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 };

254
struct timespec clock_difftime(struct timespec start, struct timespec end) {
255 256 257 258 259 260 261 262 263
  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;
264 265
}

266
void print_difftimes(void) {
267
#ifdef DEBUG
268
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
269
#else
270
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
271 272 273
#endif
}

274
void update_difftimes(struct timespec start, struct timespec end) {
275 276 277
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
278 279 280 281 282 283 284 285
  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;
  }
286
#if 1
287
  if (changed) print_difftimes();
288 289 290 291 292
#endif
}

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

293
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
Raymond Knopp's avatar
 
Raymond Knopp committed
294
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
295
}
296
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
Raymond Knopp's avatar
 
Raymond Knopp committed
297
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
298 299
}

300
#if !defined(ENABLE_ITTI)
301
void signal_handler(int sig) {
302 303 304 305 306 307
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
308

309 310 311 312
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
313 314
  } else {
    printf("trying to exit gracefully...\n");
315
    oai_exit = 1;
316 317
  }
}
318
#endif
319 320 321 322 323 324
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

325

Raymond Knopp's avatar
Raymond Knopp committed
326

327 328
void exit_fun(const char* s)
{
329

330
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
331

332
  if (s != NULL) {
333
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
334 335 336
  }

  oai_exit = 1;
337

338 339 340

    if (RC.ru == NULL)
        exit(-1); // likely init not completed, prevent crash or hang, exit now...
341
    for (ru_id=0; ru_id<RC.nb_RU;ru_id++) {
342
      if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) {
343
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
344 345
        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
      }
346
      if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
347
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
348 349
        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
      }
350 351
    }

352 353

#if defined(ENABLE_ITTI)
354 355
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
356
#endif
357 358


359
}
360

361
#ifdef XFORMS
362

363

364 365
void reset_stats(FL_OBJECT *button, long arg)
{
366
  int i,j,k;
367
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
368 369 370

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
371
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
372 373 374
	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;
375
      }
376

377 378 379
      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;
380 381


382 383 384
      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;
385 386 387 388
    }
  }
}

389
static void *scope_thread(void *arg) {
390
 
391
# ifdef ENABLE_XFORMS_WRITE_STATS
392
  FILE *eNB_stats;
393
# endif
Raymond Knopp's avatar
 
Raymond Knopp committed
394
  struct sched_param sched_param;
395
  int UE_id, CC_id;
396
  int ue_cnt=0;
397

398
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
399
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
400

Raymond Knopp's avatar
 
Raymond Knopp committed
401
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
402

403
# ifdef ENABLE_XFORMS_WRITE_STATS
404

405
  eNB_stats = fopen("eNB_stats.txt", "w");
406

407
#endif
408

Raymond Knopp's avatar
 
Raymond Knopp committed
409
  while (!oai_exit) {
410

411 412
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
413
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
414
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
415
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
416
			  RC.eNB[0][CC_id],
417 418 419
			  UE_id);
	    ue_cnt++;
	  }
420
	}
421
      }	
Florian Kaltenberger's avatar
Florian Kaltenberger committed
422
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
423
  }
424

425
  //  printf("%s",stats_buffer);
426

427
# ifdef ENABLE_XFORMS_WRITE_STATS
428

429 430 431 432 433
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
434

435
# endif
436

Raymond Knopp's avatar
 
Raymond Knopp committed
437
  pthread_exit((void*)arg);
438 439 440
}
#endif

441

442

443

Raymond Knopp's avatar
 
Raymond Knopp committed
444
#if defined(ENABLE_ITTI)
445
void *l2l1_task(void *arg) {
Raymond Knopp's avatar
 
Raymond Knopp committed
446 447 448 449 450
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
451

Raymond Knopp's avatar
 
Raymond Knopp committed
452
    /* Wait for the initialize message */
453
    printf("Wait for the ITTI initialize message\n");
454
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
455
      if (message_p != NULL) {
456 457
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
Raymond Knopp's avatar
 
Raymond Knopp committed
458
      }
459

460 461 462
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
463
      case INITIALIZE_MESSAGE:
464
	/* Start eNB thread */
465
	printf("L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
466 467
	start_eNB = 1;
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
468 469

      case TERMINATE_MESSAGE:
470 471
	printf("received terminate message\n");
	oai_exit=1;
472
        start_eNB = 0;
473 474
	itti_exit_task ();
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
475 476

      default:
477
	printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
478
	break;
479
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
480
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
481

Raymond Knopp's avatar
 
Raymond Knopp committed
482 483
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
484
/* ???? no else but seems to be UE only ??? 
Raymond Knopp's avatar
 
Raymond Knopp committed
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);

    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;

    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;

    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
502

Raymond Knopp's avatar
 
Raymond Knopp committed
503
    case MESSAGE_TEST:
504
      printf("Received %s\n", ITTI_MSG_NAME(message_p));
Raymond Knopp's avatar
 
Raymond Knopp committed
505 506 507
      break;

    default:
508
      printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
Raymond Knopp's avatar
 
Raymond Knopp committed
509 510 511 512 513
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
514
  } while(!oai_exit);
515
*/
Raymond Knopp's avatar
 
Raymond Knopp committed
516
  return NULL;
517 518 519
}
#endif

520

521
static void get_options(unsigned int *start_msc) {
522
 
523
  int tddflag, nonbiotflag;
524 525
 
  
526
  uint32_t online_log_messages;
527
  uint32_t glog_level ;
oai's avatar
oai committed
528
  uint32_t start_telnetsrv;
529

530
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
531
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
532
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
533 534 535 536 537 538 539 540 541 542 543 544
  config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); 

  if (strlen(in_path) > 0) {
      opt_type = OPT_PCAP;
      opt_enabled=1;
      printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
  }
  if (strlen(in_ip) > 0) {
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      printf("Enabling OPT for wireshark for local interface");
  }
545
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
546
  config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
547

548 549 550 551
  if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
      set_glog_onlinelog(online_log_messages);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
552
      set_glog(glog_level);
553
  }
oai's avatar
oai committed
554
  if (start_telnetsrv) {
555
     load_module_shlib("telnetsrv",NULL,0,NULL);
oai's avatar
oai committed
556 557
  }

558 559 560
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
561
      RCConfig();
562
      NB_eNB_INST = RC.nb_inst;
563
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
oai's avatar
oai committed
564 565 566 567 568 569 570 571
      if (nonbiotflag <= 0) {
         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;
      }
572
   }
573 574 575
}


576

577

578

579
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594

  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
    /* 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;
595
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    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;

615 616 617 618
//    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
619
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
620
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
621 622 623 624 625

  }

}

626

627
void init_openair0(void) {
Raymond Knopp's avatar
Raymond Knopp committed
628 629 630

  int card;
  int i;
631
  
Raymond Knopp's avatar
Raymond Knopp committed
632 633 634 635 636 637 638

  for (card=0; card<MAX_CARDS; card++) {

    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

    if(frame_parms[0]->N_RB_DL == 100) {
639 640
	  if(numerology == 0)
	  {
Raymond Knopp's avatar
Raymond Knopp committed
641 642
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
643
	openair0_cfg[card].samples_per_frame = 230400;
Raymond Knopp's avatar
Raymond Knopp committed
644 645
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
646
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
647
	openair0_cfg[card].sample_rate=30.72e6;
648
	openair0_cfg[card].samples_per_frame = 307200;
Raymond Knopp's avatar
Raymond Knopp committed
649 650 651
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
	  }else if(numerology == 1)
	  {
		openair0_cfg[card].sample_rate=61.44e6;
		openair0_cfg[card].samples_per_frame = 307200;
		openair0_cfg[card].tx_bw = 20e6;
		openair0_cfg[card].rx_bw = 20e6;
	  }else if(numerology == 2)
	  {
		openair0_cfg[card].sample_rate=122.88e6;
		openair0_cfg[card].samples_per_frame = 307200;
		openair0_cfg[card].tx_bw = 20e6;
		openair0_cfg[card].rx_bw = 20e6;
	  }else
	  {
	    printf("Un supported numerology\n");
	  }
Raymond Knopp's avatar
Raymond Knopp committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }


    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
692 693
	   RC.eNB[0][0]->frame_parms.nb_antennas_tx ,
	   RC.eNB[0][0]->frame_parms.nb_antennas_rx );
Raymond Knopp's avatar
Raymond Knopp committed
694 695 696
    openair0_cfg[card].Mod_id = 0;

    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
697

698
    openair0_cfg[card].clock_source = clock_source;
699

700

701 702
    openair0_cfg[card].tx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_tx );
    openair0_cfg[card].rx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_rx );
703

Raymond Knopp's avatar
Raymond Knopp committed
704
    for (i=0; i<4; i++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
705

Raymond Knopp's avatar
Raymond Knopp committed
706
      if (i<openair0_cfg[card].tx_num_channels)
707
	openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
Raymond Knopp's avatar
Raymond Knopp committed
708 709
      else
	openair0_cfg[card].tx_freq[i]=0.0;
710

Raymond Knopp's avatar
Raymond Knopp committed
711
      if (i<openair0_cfg[card].rx_num_channels)
712
	openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
Raymond Knopp's avatar
Raymond Knopp committed
713 714 715 716 717
      else
	openair0_cfg[card].rx_freq[i]=0.0;

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
718 719
      openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;

Raymond Knopp's avatar
Raymond Knopp committed
720

721
      openair0_cfg[card].configFilename = rf_config_file;
722
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
723 724 725 726
	     card,i, openair0_cfg[card].tx_gain[i],
	     openair0_cfg[card].rx_gain[i],
	     openair0_cfg[card].tx_freq[i],
	     openair0_cfg[card].rx_freq[i]);
727
    }
728
  } /* for loop on cards */
Raymond Knopp's avatar
 
Raymond Knopp committed
729
}
730

731

732
void wait_RUs(void) {
733

734
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
735 736 737 738 739

  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
740
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
741
  }
742
  pthread_mutex_unlock(&RC.ru_mutex);
743 744 745 746

  LOG_I(PHY,"RUs configured\n");
}

747
void wait_eNBs(void) {
748 749 750 751 752 753

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
754 755
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
756
    waiting=0;
757 758 759 760 761
    for (i=0;i<RC.nb_L1_inst;i++) {

      printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);

      for (j=0;j<RC.nb_L1_CC[i];j++) {
762 763 764
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
765 766 767
        } 
      }
    }
768 769 770
  }
  printf("eNB L1 are configured\n");
}
771

772
#if defined(ENABLE_ITTI)
773 774
/*
 * helper function to terminate a certain ITTI task
775
 */
776
void terminate_task(task_id_t task_id, module_id_t mod_id)
777
{
778 779 780 781 782 783
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
  msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}

784
extern void  free_transport(PHY_VARS_eNB *);
785 786
extern void  phy_free_RU(RU_t*);

787
int stop_L1L2(module_id_t enb_id)
788 789
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
790
  oai_exit = 1;
791

792
  if (!RC.ru) {
793
    LOG_UI(ENB_APP, "no RU configured\n");
794 795 796 797 798 799 800 801 802 803
    return -1;
  }

  /* stop trx devices, multiple carrier currently not supported by RU */
  if (RC.ru[enb_id]) {
    if (RC.ru[enb_id]->rfdevice.trx_stop_func) {
      RC.ru[enb_id]->rfdevice.trx_stop_func(&RC.ru[enb_id]->rfdevice);
      LOG_I(ENB_APP, "turned off RU rfdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
804
    }
805 806 807 808 809
    if (RC.ru[enb_id]->ifdevice.trx_stop_func) {
      RC.ru[enb_id]->ifdevice.trx_stop_func(&RC.ru[enb_id]->ifdevice);
      LOG_I(ENB_APP, "turned off RU ifdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
810
    }
811 812 813
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
814 815 816 817 818
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
819
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
820
  kill_eNB_proc(enb_id);
821 822
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
823
  oai_exit = 0;
824 825 826 827
  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]);
  }
828
  phy_free_RU(RC.ru[enb_id]);
829
  free_lte_top();
830 831 832 833
  return 0;
}

/*
834
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
835
 */
836
int restart_L1L2(module_id_t enb_id)
837
{
838 839 840
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
841 842 843 844 845 846

  LOG_W(ENB_APP, "restarting lte-softmodem\n");

  /* block threads */
  sync_var = -1;

847 848
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
849 850
  }

851 852 853 854 855
  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]);
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870

  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
  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");
  }
  if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
    LOG_E(PDCP, "Create task for L2L1 failed\n");
    return -1;
  } else {
    LOG_I(PDCP, "Re-created task for L2L1 successfully\n");
  }

871 872 873 874 875
  /* 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);
876 877
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
878

879 880 881 882 883 884
  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();
885 886 887 888 889 890 891 892

  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;
893
}
894
#endif
895

896
static  void wait_nfapi_init(char *thread_name) {
897 898 899 900 901 902 903 904 905

  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
  
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
  
  pthread_mutex_unlock(&nfapi_sync_mutex);
  
906 907 908 909 910
  /*
   * Raphael Defosseux: temporary workaround for CI
   * -- Repeating the message thrice to make sure
   * -- it is present during flush.
   */
911
  printf( "NFAPI: got sync (%s)\n", thread_name);
912 913 914 915
  printf( "NFAPI: got sync (%s)\n", thread_name);
  printf( "NFAPI: got sync (%s)\n", thread_name);
  fflush(stdout);
  fflush(stderr);
916 917
}

918 919
int main( int argc, char **argv )
{
920
  int i;
921
#if defined (XFORMS)
Raymond Knopp's avatar
 
Raymond Knopp committed
922
  void *status;
923
#endif
924

Raymond Knopp's avatar
 
Raymond Knopp committed
925
  int CC_id;
926
  int ru_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
927
#if defined (XFORMS)
928 929
  int ret;
#endif
930
  unsigned int start_msc=0;
931

932 933 934 935
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
936

937
  mode = normal_txrx;
938
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
939

940
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
941

Raymond Knopp's avatar
 
Raymond Knopp committed
942
  set_latency_target();
943

944
  logInit();
Raymond Knopp's avatar
Raymond Knopp committed
945

946
  printf("Reading in command-line options\n");
947

948
  get_options (&start_msc);
949
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
950 951
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
952
  }
Raymond Knopp's avatar
Raymond Knopp committed
953 954


955
#if T_TRACER
956
  T_Config_Init();
957 958
#endif

959

Florian Kaltenberger's avatar
Florian Kaltenberger committed
960

961 962
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
963

964
  printf("configuring for RAU/RRU\n");
965

966
  if (opp_enabled ==1) {
967
    reset_opp_meas();
968 969
  }
  cpuf=get_cpu_freq_GHz();
970

971 972
#if defined(ENABLE_ITTI)

973
  printf("ITTI init, useMME: %i\n" ,EPC_MODE_ENABLED);
974

Cedric Roux's avatar
Cedric Roux committed
975
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
976

977
  // initialize mscgen log after ITTI
978 979 980
  if (start_msc) {
     load_module_shlib("msc",NULL,0,&msc_interface);
  }
981
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
982
#endif
983

984
  if (opt_type != OPT_NONE) {
laurent's avatar
laurent committed
985
    if (init_opt(in_path, in_ip) == -1)
986 987
      LOG_E(OPT,"failed to run OPT \n");
  }
988

989
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
990 991 992
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
993
#endif
994

995

Raymond Knopp's avatar
 
Raymond Knopp committed
996 997
  check_clock();

998 999 1000 1001 1002 1003
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

Raymond Knopp's avatar
 
Raymond Knopp committed
1004 1005


Raymond Knopp's avatar
Raymond Knopp committed
1006
  
1007
  printf("Before CC \n");
Raymond Knopp's avatar
Raymond Knopp committed
1008
  
1009
  printf("Runtime table\n");
1010
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
Raymond Knopp's avatar
Raymond Knopp committed
1011 1012
  
    
laurent's avatar
laurent committed
1013
#ifndef DEADLINE_SCHEDULER
1014
  
1015
  printf("NO deadline scheduler\n");
1016
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
1017 1018 1019 1020 1021
  
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
1022
#ifdef CPU_AFFINITY
1023 1024 1025
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1026
    if (s != 0) {
1027 1028
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
1029
    }
1030 1031
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
1032
#endif
1033
  
1034 1035
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1036 1037 1038 1039
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
1040
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
1041 1042 1043 1044 1045
  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);
1046
    }
1047
  }
1048
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
1049
#endif
1050 1051 1052 1053

  /* Read configuration */
  if (RC.nb_inst > 0)
    read_config_and_init();
1054
  
1055 1056 1057 1058 1059
  /* Start the agent. If it is turned off in the configuration, it won't start */
  RCconfig_flexran();
  for (i = 0; i < RC.nb_inst; i++) {
    flexran_agent_start(i);
  }
Raymond Knopp's avatar
Raymond Knopp committed
1060
    
1061
  if (RC.nb_inst > 0)  {
1062 1063 1064 1065

    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
1066
    }
1067 1068 1069 1070

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
      itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
1071
    }
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081

    if (RC.rrc[0]->node_type != ngran_eNB_DU) {
#ifdef PDCP_USE_NETLINK
      printf("PDCP netlink\n");
      netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES)
      pdcp_netlink_init();
#endif
#endif
    }
1082 1083
  }
  else {
1084 1085
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1086
  }
Raymond Knopp's avatar
Raymond Knopp committed
1087

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097

  if (RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU) {
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
    pdcp_run(&ctxt);
  }

1098 1099 1100
  /* start threads if only L1 or not a CU */
  if (RC.nb_inst == 0 ||
      !(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
Raymond Knopp's avatar
Raymond Knopp committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
      // init UE_PF_PO and mutex lock
    pthread_mutex_init(&ue_pf_po_mutex, NULL);
    memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
    
    mlockall(MCL_CURRENT | MCL_FUTURE);
    
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
    
#ifdef XFORMS
    int UE_id;
    
    printf("XFORMS\n");
1114
    
Raymond Knopp's avatar
Raymond Knopp committed
1115 1116 1117
    if (do_forms==1) {
      fl_initialize (&argc, argv, NULL, 0, 0);
      
1118
      form_stats_l2 = create_form_stats_form();
1119 1120 1121
      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");
1122
      
1123
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1124 1125 1126 1127
	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);
1128
	  
1129 1130 1131 1132 1133 1134 1135
	  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");
	  }
1136 1137
	} // CC_id
      } // UE_id
Raymond Knopp's avatar
Raymond Knopp committed
1138 1139 1140 1141 1142 1143 1144 1145
      
      ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
      
      if (ret == 0)
	pthread_setname_np( forms_thread, "xforms" );
      
      printf("Scope thread created, ret=%d\n",ret);
    }
1146
    
Raymond Knopp's avatar
Raymond Knopp committed
1147
#endif
1148
    
Raymond Knopp's avatar
Raymond Knopp committed
1149
    rt_sleep_ns(10*100000000ULL);
1150
    
Raymond Knopp's avatar
Raymond Knopp committed
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
    if (nfapi_mode)
      {
	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);
      }
    
    const char *nfapi_mode_str = "<UNKNOWN>";
    
    switch(nfapi_mode) {
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
    case 0:
      nfapi_mode_str = "MONOLITHIC";
      break;
    case 1:
      nfapi_mode_str = "PNF";
      break;
    case 2:
      nfapi_mode_str = "VNF";
      break;
    default:
      nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
      break;
Raymond Knopp's avatar
Raymond Knopp committed
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    }
    printf("NFAPI MODE:%s\n", nfapi_mode_str);
    
    if (nfapi_mode==2) // VNF
      wait_nfapi_init("main?");
    
    
    printf("START MAIN THREADS\n");
    
    // start the main threads
    
1184
    number_of_cards = 1;    
1185
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
1186
    if (RC.nb_L1_inst > 0) {
1187
      printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
1188
      init_eNB(single_thread_flag,wait_for_sync);
1189 1190
      //      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);
Raymond Knopp's avatar
 
Raymond Knopp committed
1191
    }
Raymond Knopp's avatar
Raymond Knopp committed
1192
    
1193
    printf("wait_eNBs()\n");
1194
    wait_eNBs();
Raymond Knopp's avatar
Raymond Knopp committed
1195
    
1196
    printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
1197 1198 1199 1200 1201 1202 1203 1204
    if (RC.nb_RU >0) {
      printf("Initializing RU threads\n");
      init_RU(rf_config_file);
      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+chain_offset;
      }
    }
Raymond Knopp's avatar
Raymond Knopp committed
1205
    
1206
    config_sync_var=0;
Raymond Knopp's avatar
Raymond Knopp committed
1207
    
1208 1209 1210
    if (nfapi_mode==1) { // PNF
      wait_nfapi_init("main?");
    }
Raymond Knopp's avatar
Raymond Knopp committed
1211
    
1212
    printf("wait RUs\n");
1213
    wait_RUs();
1214 1215
    printf("ALL RUs READY!\n");
    printf("RC.nb_RU:%d\n", RC.nb_RU);
1216
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
1217
    printf("ALL RUs ready - init eNBs\n");
Raymond Knopp's avatar
Raymond Knopp committed
1218
    
1219
    if (nfapi_mode != 1 && nfapi_mode != 2)
Raymond Knopp's avatar
Raymond Knopp committed
1220 1221 1222 1223
      {
	printf("Not NFAPI mode - call init_eNB_afterRU()\n");
	init_eNB_afterRU();
      }
1224
    else
Raymond Knopp's avatar
Raymond Knopp committed
1225 1226 1227
      {
	printf("NFAPI mode - DO NOT call init_eNB_afterRU()\n");
      }
1228
    
1229
    printf("ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
1230 1231 1232
    
    
    // connect the TX/RX buffers
1233
 
Raymond Knopp's avatar
Raymond Knopp committed
1234 1235 1236 1237 1238 1239 1240 1241 1242
    sleep(1); /* wait for thread activation */
    
    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);
  }
1243

Raymond Knopp's avatar
Raymond Knopp committed
1244
    // wait for end of program
Raymond Knopp's avatar
 
Raymond Knopp committed
1245 1246
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
1247 1248

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1249 1250
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
1251
  printf("Returned from ITTI signal handler\n");
1252
  oai_exit=1;
1253
  printf("oai_exit=%d\n",oai_exit);
1254
#else
1255

Raymond Knopp's avatar
 
Raymond Knopp committed
1256
  while (oai_exit==0)
1257
    rt_sleep_ns(100000000ULL);
1258
  printf("Terminating application - oai_exit=%d\n",oai_exit);
1259

1260
#endif
1261

Raymond Knopp's avatar
 
Raymond Knopp committed
1262
  // stop threads
1263 1264


1265 1266
  if (RC.nb_inst == 0 ||
      !(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
Raymond Knopp's avatar
Raymond Knopp committed
1267 1268 1269 1270 1271 1272 1273 1274 1275
    int UE_id;
#ifdef XFORMS
    printf("waiting for XFORMS thread\n");
    
    if (do_forms==1) {
      pthread_join(forms_thread,&status);
      fl_hide_form(form_stats->stats_form);
      fl_free_form(form_stats->stats_form);
      
1276 1277
      fl_hide_form(form_stats_l2->stats_form);
      fl_free_form(form_stats_l2->stats_form);
Raymond Knopp's avatar
Raymond Knopp committed
1278
      
1279
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1280 1281 1282 1283
	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
1284
      }
Raymond Knopp's avatar
Raymond Knopp committed
1285 1286
    }
    
1287 1288
#endif

Raymond Knopp's avatar
Raymond Knopp committed
1289 1290 1291 1292 1293 1294 1295
    printf("stopping MODEM threads\n");
    
    // cleanup
    for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
      stop_ru(RC.ru[ru_id]);
    }
    
Robert Schmidt's avatar
Robert Schmidt committed
1296
    stop_eNB(NB_eNB_INST);
1297
    stop_RU(RC.nb_RU);
1298 1299 1300 1301 1302 1303 1304 1305
    /* 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]);
      }
    }
1306
    for (int inst = 0; inst < RC.nb_RU; inst++) {
1307 1308
      phy_free_RU(RC.ru[inst]);
    }
1309
    free_lte_top();
1310

1311

Raymond Knopp's avatar
Raymond Knopp committed
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
    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);
    
    // *** Handle per CC_id openair0
    
    
1323
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
1324 1325 1326 1327 1328 1329 1330 1331
      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;
      }
      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
1332
    }
Raymond Knopp's avatar
Raymond Knopp committed
1333 1334 1335 1336 1337 1338
  }

  printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  end_configmodule();
  printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);

1339
  
1340
  if (opt_enabled == 1)
1341
    terminate_opt();
1342
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1343
  logClean();
1344

1345
  printf("Bye.\n");
1346
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1347 1348
  return 0;
}