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

38 39
#include "T.h"

40
#include "rt_wrapper.h"
41

42

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

45
#include "assertions.h"
46
#include "msc.h"
47 48

#include "PHY/types.h"
49

50
#include "PHY/defs_eNB.h"
51
#include "common/ran_context.h"
52
#include "common/config/config_userapi.h"
oai's avatar
oai committed
53
#include "common/utils/load_module_shlib.h"
54
#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
55
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
56

Raymond Knopp's avatar
 
Raymond Knopp committed
57
#include "../../ARCH/COMMON/common_lib.h"
58
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
59

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

62 63 64
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
65

66 67 68 69
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
70 71 72 73 74 75

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

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

88
#if defined(ENABLE_ITTI)
89 90
#include "intertask_interface_init.h"
#include "create_tasks.h"
91 92
#endif

93 94
#include "PHY/INIT/phy_init.h"

95 96
#include "system.h"

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

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
#if defined(ENABLE_ITTI)
131 132
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
133
#endif
Raymond Knopp's avatar
Raymond Knopp committed
134
volatile int             oai_exit = 0;
135

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

139
unsigned int                    mmapped_dma=0;
140
int                             single_thread_flag=1;
141

142
static int8_t                     threequarter_fs=0;
143

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

147
char logmem_filename[1024] = {0};
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
#if defined(ENABLE_ITTI)
153
static char                    *itti_dump_file = NULL;
Raymond Knopp's avatar
 
Raymond Knopp committed
154 155
#endif

156
int UE_scan = 1;
157
int UE_scan_carrier = 0;
158 159
runmode_t mode = normal_txrx;

160 161
FILE *input_fd=NULL;

162

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

173
double rx_gain_off = 0.0;
174

Raymond Knopp's avatar
 
Raymond Knopp committed
175
double sample_rate=30.72e6;
176
double bw = 10.0e6;
177

178
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
179

180 181
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
182
int chain_offset=0;
183
int phy_test = 0;
184
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
185

186 187 188
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

189 190
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
191

Raymond Knopp's avatar
 
Raymond Knopp committed
192 193 194
char ref[128] = "internal";
char channels[128] = "0";

195
int                      rx_input_level_dBm;
196

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

205 206

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

213

214 215
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
216

217 218 219 220 221 222
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);

223
int transmission_mode=1;
224
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
225
int numerology = 0;
226 227
int codingw = 0;
int fepw = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
228

229

230

231 232 233
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

234 235 236 237
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

238 239
extern char uecap_xer[1024];
char uecap_xer_in=0;
240

241
int oaisim_flag=0;
242
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
Raymond Knopp's avatar
 
Raymond Knopp committed
243

Cedric Roux's avatar
Cedric Roux committed
244 245 246 247
/* 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
248

249 250 251
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

252 253 254 255 256
/*---------------------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 };

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

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

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

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

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

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

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

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

328

Raymond Knopp's avatar
Raymond Knopp committed
329

330 331
void exit_fun(const char* s)
{
332

333
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
334

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

  oai_exit = 1;
340

341 342 343

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

355 356

#if defined(ENABLE_ITTI)
357 358
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
359
#endif
360 361


362
}
363

364
#ifdef XFORMS
365

366

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

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

380 381 382
      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;
383 384


385 386 387
      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;
388 389 390 391
    }
  }
}

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

401
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
402
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
403

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

406
# ifdef ENABLE_XFORMS_WRITE_STATS
407

408
  eNB_stats = fopen("eNB_stats.txt", "w");
409

410
#endif
411

Raymond Knopp's avatar
 
Raymond Knopp committed
412
  while (!oai_exit) {
413

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

428
  //  printf("%s",stats_buffer);
429

430
# ifdef ENABLE_XFORMS_WRITE_STATS
431

432 433 434 435 436
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
437

438
# endif
439

Raymond Knopp's avatar
 
Raymond Knopp committed
440
  pthread_exit((void*)arg);
441 442 443
}
#endif

444

445

446

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
454

Raymond Knopp's avatar
 
Raymond Knopp committed
455
    /* Wait for the initialize message */
456
    printf("Wait for the ITTI initialize message\n");
457
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
458
      if (message_p != NULL) {
459 460
	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
461
      }
462

463 464 465
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

      default:
480 481
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
482
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
483
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
484

Raymond Knopp's avatar
 
Raymond Knopp committed
485 486
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
487
/* ???? no else but seems to be UE only ??? 
Raymond Knopp's avatar
 
Raymond Knopp committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
  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;
505

Raymond Knopp's avatar
 
Raymond Knopp committed
506 507 508 509 510 511 512 513 514 515 516
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;

    default:
      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
      break;
    }

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

523

524
static void get_options(void) {
525
 
526
  int tddflag, nonbiotflag;
527 528
 
  
529 530
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;
oai's avatar
oai committed
531
  uint32_t start_telnetsrv;
532

533
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
534
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
535 536 537 538 539 540 541 542 543 544 545 546 547

  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");
  }
548 549 550 551 552 553 554 555

  config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
  if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
      set_glog_onlinelog(online_log_messages);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
      set_glog(glog_level, -1);
  }
556
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
557 558
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
559
  if (start_telnetsrv) {
560
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
561
  }
562 563 564 565 566 567
  if (strlen(logmem_filename) > 0) {
    log_mem_filename = &logmem_filename[0];
    log_mem_flag = 1;
    printf("Enabling OPT for log save at memory %s\n",log_mem_filename);
    logInit_log_mem();
  }
oai's avatar
oai committed
568

569

570

571 572 573
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
574
      RCConfig();
575 576
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
577
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
oai's avatar
oai committed
578 579 580 581 582 583 584 585
      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;
      }
586
   }
587 588 589
}


590

591

592

593
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608

  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;
609
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
    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;

629 630 631 632
//    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
633
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
634
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
635 636 637 638 639

  }

}

640

641
void init_openair0(void) {
Raymond Knopp's avatar
Raymond Knopp committed
642 643 644

  int card;
  int i;
645
  
Raymond Knopp's avatar
Raymond Knopp committed
646 647 648 649 650 651 652

  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) {
653 654
	  if(numerology == 0)
	  {
Raymond Knopp's avatar
Raymond Knopp committed
655 656
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
657
	openair0_cfg[card].samples_per_frame = 230400;
Raymond Knopp's avatar
Raymond Knopp committed
658 659
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
660
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
661
	openair0_cfg[card].sample_rate=30.72e6;
662
	openair0_cfg[card].samples_per_frame = 307200;
Raymond Knopp's avatar
Raymond Knopp committed
663 664 665
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
	  }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
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
    } 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,
706 707
	   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
708 709 710
    openair0_cfg[card].Mod_id = 0;

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

712
    openair0_cfg[card].clock_source = clock_source;
713

714

715 716
    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 );
717

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

Raymond Knopp's avatar
Raymond Knopp committed
720
      if (i<openair0_cfg[card].tx_num_channels)
721
	openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
Raymond Knopp's avatar
Raymond Knopp committed
722 723
      else
	openair0_cfg[card].tx_freq[i]=0.0;
724

Raymond Knopp's avatar
Raymond Knopp committed
725
      if (i<openair0_cfg[card].rx_num_channels)
726
	openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
Raymond Knopp's avatar
Raymond Knopp committed
727 728 729 730 731
      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];
732 733
      openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;

Raymond Knopp's avatar
Raymond Knopp committed
734

735
      openair0_cfg[card].configFilename = rf_config_file;
736
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
737 738 739 740
	     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]);
741
    }
742
  } /* for loop on cards */
Raymond Knopp's avatar
 
Raymond Knopp committed
743
}
744

745

746
void wait_RUs(void) {
747

748
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
749 750 751 752 753

  // 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);
754
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
755
  }
756
  pthread_mutex_unlock(&RC.ru_mutex);
757 758 759 760

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

761
void wait_eNBs(void) {
762 763 764 765 766 767

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
768 769
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
770
    waiting=0;
771 772 773 774 775
    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++) {
776 777 778
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
779 780 781
        } 
      }
    }
782 783 784
  }
  printf("eNB L1 are configured\n");
}
785

786
#if defined(ENABLE_ITTI)
787 788
/*
 * helper function to terminate a certain ITTI task
789
 */
790
void terminate_task(task_id_t task_id, module_id_t mod_id)
791
{
792 793 794 795 796 797
  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);
}

798
extern void  free_transport(PHY_VARS_eNB *);
799 800
extern void  phy_free_RU(RU_t*);

801
int stop_L1L2(module_id_t enb_id)
802 803
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
804
  oai_exit = 1;
805

806 807 808 809 810 811 812 813 814 815 816 817
  if (!RC.ru) {
    LOG_F(ENB_APP, "no RU configured\n");
    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");
818
    }
819 820 821 822 823
    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");
824
    }
825 826 827
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
828 829 830 831 832
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
833
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
834
  kill_eNB_proc(enb_id);
835 836
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
837
  oai_exit = 0;
838 839 840 841
  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]);
  }
842
  phy_free_RU(RC.ru[enb_id]);
843
  free_lte_top();
844 845 846 847
  return 0;
}

/*
848
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
849
 */
850
int restart_L1L2(module_id_t enb_id)
851
{
852 853 854
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
855 856 857 858 859 860

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

  /* block threads */
  sync_var = -1;

861 862
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
863 864
  }

865 866 867 868 869
  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]);
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884

  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");
  }

885 886 887 888 889
  /* 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);
890 891
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
892

893 894 895 896 897 898
  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();
899 900 901 902 903 904 905 906

  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;
907
}
908
#endif
909

910
static  void wait_nfapi_init(char *thread_name) {
911 912 913 914 915 916 917 918 919 920 921 922

  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);
  
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

923 924
int main( int argc, char **argv )
{
925
  int i;
926
#if defined (XFORMS)
Raymond Knopp's avatar
 
Raymond Knopp committed
927
  void *status;
928
#endif
929

Raymond Knopp's avatar
 
Raymond Knopp committed
930
  int CC_id;
931
  int ru_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
932
#if defined (XFORMS)
933 934
  int ret;
#endif
935

936 937 938 939
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
940

941
  mode = normal_txrx;
942
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
943

944
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
945

Raymond Knopp's avatar
 
Raymond Knopp committed
946
  set_latency_target();
947

948
  logInit();
Raymond Knopp's avatar
Raymond Knopp committed
949

950
  printf("Reading in command-line options\n");
951

952
  get_options (); 
953
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
954 955
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
956
  }
Raymond Knopp's avatar
Raymond Knopp committed
957 958


959
#if T_TRACER
960
  T_Config_Init();
961 962
#endif

963

Florian Kaltenberger's avatar
Florian Kaltenberger committed
964

965 966
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
967

968
  printf("configuring for RAU/RRU\n");
969

970
  if (opp_enabled ==1) {
971
    reset_opp_meas();
972 973
  }
  cpuf=get_cpu_freq_GHz();
974

975
#if defined(ENABLE_ITTI)
976
  log_set_instance_type (LOG_INSTANCE_ENB);
977

978
  printf("ITTI init\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
979
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
980

981 982
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
983
#endif
984

985 986
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
987

988 989
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
990
    else
991
      radio_type = RADIO_TYPE_TDD;
992

993 994 995
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
996

997
#ifdef PDCP_USE_NETLINK
998
  printf("PDCP netlink\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
999
  netlink_init();
1000 1001 1002
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
1003 1004
#endif

1005
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1006 1007 1008
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
1009
#endif
1010

1011

Raymond Knopp's avatar
 
Raymond Knopp committed
1012 1013
  check_clock();

1014 1015 1016 1017 1018 1019
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1020 1021


Raymond Knopp's avatar
 
Raymond Knopp committed
1022

1023
  printf("Before CC \n");
1024

1025
  printf("Runtime table\n");
1026
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
1027 1028


laurent's avatar
laurent committed
1029
#ifndef DEADLINE_SCHEDULER
1030
  
1031
  printf("NO deadline scheduler\n");
1032
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
1033 1034 1035 1036 1037
  
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
1038
#ifdef CPU_AFFINITY
1039 1040 1041
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1042
    if (s != 0) {
1043 1044
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
1045
    }
1046 1047
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
1048
#endif
1049
  
1050 1051
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1052 1053 1054 1055
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
1056
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
1057 1058 1059 1060 1061
  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);
1062
    }
1063
  }
1064
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
1065
#endif
1066
  
1067

1068
  
1069
  
winckel's avatar
winckel committed
1070
#if defined(ENABLE_ITTI)
1071
  if (RC.nb_inst > 0)  {
1072
    
Raymond Knopp's avatar
Raymond Knopp committed
1073
    // don't create if node doesn't connect to RRC/S1/GTP
1074 1075 1076 1077
      if (create_tasks(1) < 0) {
        printf("cannot create ITTI tasks\n");
        exit(-1); // need a softer mode
      }
1078 1079 1080
    printf("ITTI tasks created\n");
  }
  else {
1081 1082
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1083
  }
winckel's avatar
winckel committed
1084
#endif
1085

1086
  /* Start the agent. If it is turned off in the configuration, it won't start */
1087 1088 1089
  RCconfig_flexran();
  for (i = 0; i < RC.nb_L1_inst; i++) {
    flexran_agent_start(i);
1090
  }
1091 1092 1093

  // init UE_PF_PO and mutex lock
  pthread_mutex_init(&ue_pf_po_mutex, NULL);
1094
  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
1095
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1096
  mlockall(MCL_CURRENT | MCL_FUTURE);
1097
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1098 1099
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
1100
  
1101
#ifdef XFORMS
1102
  int UE_id;
1103
  
1104 1105
  printf("XFORMS\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
1106 1107
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
1108
    
1109
      form_stats_l2 = create_form_stats_form();
1110 1111 1112
      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");
1113
      
1114
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1115 1116 1117 1118
	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);
1119
	  
1120 1121 1122 1123 1124 1125 1126
	  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");
	  }
1127 1128
	} // CC_id
      } // UE_id
1129
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1130
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
1131
    
1132 1133
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
1134
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1135 1136
    printf("Scope thread created, ret=%d\n",ret);
  }
1137
  
1138
#endif
1139
  
1140
  rt_sleep_ns(10*100000000ULL);
Cedric Roux's avatar
Cedric Roux committed
1141

1142 1143 1144 1145 1146 1147
  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);
  }
1148
  
1149 1150 1151 1152 1153 1154 1155
  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);
  }

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
  const char *nfapi_mode_str = "<UNKNOWN>";

  switch(nfapi_mode) {
    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;
  }
  printf("NFAPI MODE:%s\n", nfapi_mode_str);

  if (nfapi_mode==2) // VNF
    wait_nfapi_init("main?");

  printf("START MAIN THREADS\n");
1178
  
1179
  // start the main threads
1180

1181
    number_of_cards = 1;    
1182
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
1183
    if (RC.nb_L1_inst > 0) {
1184
      printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
1185
      init_eNB(single_thread_flag,wait_for_sync);
1186 1187
      //      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
1188
    }
1189

1190
    printf("wait_eNBs()\n");
1191 1192
    wait_eNBs();

1193
    printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
1194 1195 1196 1197 1198 1199 1200 1201
    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;
      }
    }
1202

1203 1204 1205 1206 1207 1208 1209
    config_sync_var=0;

    if (nfapi_mode==1) { // PNF
      wait_nfapi_init("main?");
    }

    printf("wait RUs\n");
1210
    wait_RUs();
1211 1212
    printf("ALL RUs READY!\n");
    printf("RC.nb_RU:%d\n", RC.nb_RU);
1213
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
    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");
    }
1225
    
1226
    printf("ALL RUs ready - ALL eNBs ready\n");
1227 1228
  
  
1229
  // connect the TX/RX buffers
1230
 
1231
  
1232
  printf("Sending sync to all threads\n");
1233
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1234
  pthread_mutex_lock(&sync_mutex);
1235
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1236 1237
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
1238

1239
  // wait for end of program
Raymond Knopp's avatar
 
Raymond Knopp committed
1240 1241
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
1242 1243

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1244 1245
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
1246
  printf("Returned from ITTI signal handler\n");
1247
  oai_exit=1;
1248
  printf("oai_exit=%d\n",oai_exit);
1249
#else
1250

Raymond Knopp's avatar
 
Raymond Knopp committed
1251
  while (oai_exit==0)
1252
    rt_sleep_ns(100000000ULL);
1253
  printf("Terminating application - oai_exit=%d\n",oai_exit);
1254

1255
#endif
1256

Raymond Knopp's avatar
 
Raymond Knopp committed
1257
  // stop threads
1258
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
1259
  printf("waiting for XFORMS thread\n");
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269

  if (do_forms==1) {
    pthread_join(forms_thread,&status);
    fl_hide_form(form_stats->stats_form);
    fl_free_form(form_stats->stats_form);

      fl_hide_form(form_stats_l2->stats_form);
      fl_free_form(form_stats_l2->stats_form);

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1270 1271 1272 1273
	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
1274
      }
1275 1276
  }

1277 1278
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1279
  printf("stopping MODEM threads\n");
1280

Raymond Knopp's avatar
 
Raymond Knopp committed
1281
  // cleanup
1282 1283
  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
    stop_ru(RC.ru[ru_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1284
  }
1285

Robert Schmidt's avatar
Robert Schmidt committed
1286 1287
    stop_eNB(NB_eNB_INST);
    stop_RU(NB_RU);
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
    /* 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]);
      }
    }
    for (int inst = 0; inst < NB_RU; inst++) {
      phy_free_RU(RC.ru[inst]);
    }
1299
    free_lte_top();
1300

1301 1302 1303
  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__);
1304

Raymond Knopp's avatar
 
Raymond Knopp committed
1305 1306
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
1307

1308 1309 1310
  pthread_cond_destroy(&nfapi_sync_cond);
  pthread_mutex_destroy(&nfapi_sync_mutex);

1311
  pthread_mutex_destroy(&ue_pf_po_mutex);
1312

Raymond Knopp's avatar
Raymond Knopp committed
1313
  // *** Handle per CC_id openair0
1314

1315
    for(ru_id=0; ru_id<NB_RU; ru_id++) {
1316 1317 1318 1319 1320 1321 1322 1323
      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
1324
    }
1325
  
1326
  if (opt_enabled == 1)
1327
    terminate_opt();
1328
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1329
  logClean();
1330

1331
  printf("Bye.\n");
1332
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1333 1334
  return 0;
}