lte-softmodem.c 36.4 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
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
knopp's avatar
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
knopp's avatar
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

knopp's avatar
knopp committed
54
#include "../../ARCH/COMMON/common_lib.h"
55
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
knopp committed
56

knopp's avatar
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"
nikaeinn's avatar
nikaeinn 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"
nikaeinn's avatar
nikaeinn 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 87
#include "intertask_interface_init.h"
#include "create_tasks.h"
88 89
#endif

knopp's avatar
knopp committed
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;

knopp's avatar
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]
knopp's avatar
knopp committed
130

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

137
clock_source_t clock_source = internal;
138
static int wait_for_sync = 0;
knopp's avatar
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];
gauthier's avatar
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;
knopp's avatar
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}};
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}};
gauthier's avatar
gauthier committed
168
#endif
knopp's avatar
knopp committed
169

170
double rx_gain_off = 0.0;
171

knopp's avatar
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

knopp's avatar
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
knopp's avatar
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;
222
int numerology = 0;
223 224
int codingw = 0;
int fepw = 0;
knopp's avatar
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};
knopp's avatar
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;
knopp's avatar
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) {
knopp's avatar
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) {
knopp's avatar
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
knopp's avatar
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;
knopp's avatar
knopp committed
399
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
400

knopp's avatar
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

knopp's avatar
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);
knopp's avatar
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

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

441

442

443

knopp's avatar
knopp committed
444
#if defined(ENABLE_ITTI)
445
void *l2l1_task(void *arg) {
knopp's avatar
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

knopp's avatar
knopp committed
452
    /* Wait for the initialize message */
453
    printf("Wait for the ITTI initialize message\n");
454
    do {
knopp's avatar
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);
knopp's avatar
knopp committed
458
      }
459

460 461 462
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
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;
knopp's avatar
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;
knopp's avatar
knopp committed
475 476

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

knopp's avatar
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 ??? 
knopp's avatar
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

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

    default:
508
      printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
knopp's avatar
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
*/
knopp's avatar
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

knopp's avatar
knopp committed
579
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
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;
knopp's avatar
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];
knopp's avatar
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];
knopp's avatar
knopp committed
621 622 623 624 625

  }

}

knopp's avatar
knopp committed
626

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

  int card;
  int i;
631
  
knopp's avatar
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)
	  {
knopp's avatar
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;
knopp's avatar
knopp committed
644 645
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
646
      } else {
knopp's avatar
knopp committed
647
	openair0_cfg[card].sample_rate=30.72e6;
648
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
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");
	  }
knopp's avatar
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 );
knopp's avatar
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

knopp's avatar
knopp committed
704
    for (i=0; i<4; i++) {
705

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

knopp's avatar
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] ;
knopp's avatar
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;

knopp's avatar
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 */
knopp's avatar
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(module_id_t mod_id, task_id_t from, task_id_t to)
777
{
778 779
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
      itti_get_task_name(from), from, itti_get_task_name(to), to);
780
  MessageDef *msg;
781 782
  msg = itti_alloc_new_message (from, TERMINATE_MESSAGE);
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
783 784
}

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

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

793
  if (!RC.ru) {
794
    LOG_UI(ENB_APP, "no RU configured\n");
795 796 797 798 799 800 801 802 803 804
    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");
805
    }
806 807 808 809 810
    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");
811
    }
812 813 814
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
815 816 817
  }

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

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

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

  /* block threads */
  sync_var = -1;

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

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

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

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

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

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

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

  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);
  
907 908 909 910 911
  /*
   * Raphael Defosseux: temporary workaround for CI
   * -- Repeating the message thrice to make sure
   * -- it is present during flush.
   */
912
  printf( "NFAPI: got sync (%s)\n", thread_name);
913 914 915 916
  printf( "NFAPI: got sync (%s)\n", thread_name);
  printf( "NFAPI: got sync (%s)\n", thread_name);
  fflush(stdout);
  fflush(stderr);
917 918
}

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

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

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

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

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

knopp's avatar
knopp committed
943
  set_latency_target();
944

945
  logInit();
knopp's avatar
knopp committed
946

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

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


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

960

961

962 963
  //randominit (0);
  set_taus_seed (0);
knopp's avatar
knopp committed
964

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

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

972 973
#if defined(ENABLE_ITTI)

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

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

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

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

990
#ifdef PDCP_USE_NETLINK
991
  printf("PDCP netlink\n");
knopp's avatar
knopp committed
992
  netlink_init();
993 994 995
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
996 997
#endif

998
#if !defined(ENABLE_ITTI)
knopp's avatar
knopp committed
999 1000 1001
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
1002
#endif
1003

1004

knopp's avatar
knopp committed
1005 1006
  check_clock();

1007 1008 1009 1010 1011 1012
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

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

knopp's avatar
knopp committed
1013 1014


knopp's avatar
knopp committed
1015

1016
  printf("Before CC \n");
1017

1018
  printf("Runtime table\n");
1019
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
1020 1021


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

1061
  
1062
  
1063
#if defined(ENABLE_ITTI)
1064
  if (RC.nb_inst > 0)  {
1065
    
knopp's avatar
knopp committed
1066
    // don't create if node doesn't connect to RRC/S1/GTP
1067 1068 1069 1070
      if (create_tasks(1) < 0) {
        printf("cannot create ITTI tasks\n");
        exit(-1); // need a softer mode
      }
1071 1072 1073
    printf("ITTI tasks created\n");
  }
  else {
1074 1075
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1076
  }
1077
#endif
1078

1079
  /* Start the agent. If it is turned off in the configuration, it won't start */
1080 1081 1082
  RCconfig_flexran();
  for (i = 0; i < RC.nb_L1_inst; i++) {
    flexran_agent_start(i);
1083
  }
1084 1085