lte-softmodem.c 61 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
3
    Copyright(c) 1999 - 2014 Eurecom
4

5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
19
    see <http://www.gnu.org/licenses/>.
20

21 22 23
   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
24
   OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

28
*******************************************************************************/
29

30 31
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
33 34 35
 * \date 2012
 * \version 0.1
 * \company Eurecom
36
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
37 38 39
 * \note
 * \warning
 */
40
#define _GNU_SOURCE
41 42 43 44 45 46 47 48
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
49
#include <linux/sched.h>
50 51 52
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
53
#include <sys/sysinfo.h>
54
#include "rt_wrapper.h"
55

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

58
#include "assertions.h"
59
#include "msc.h"
60 61

#include "PHY/types.h"
62

63
#include "PHY/defs.h"
64
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
65
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
66

67 68
#include "../../ARCH/COMMON/common_lib.h"

69
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
70 71 72 73 74 75 76 77 78

#include "PHY/vars.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

#include "../../SIMU/USER/init_lte.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
79
#include "LAYER2/MAC/proto.h"
80 81 82 83 84 85 86 87
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
nikaeinn's avatar
nikaeinn committed
88
#include "UTIL/OTG/otg_tx.h"
89
#include "UTIL/OTG/otg_externs.h"
90 91
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
92
#include "UTIL/OPT/opt.h"
93
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
94
//#include "PHY/TOOLS/time_meas.h"
95

96 97 98 99
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

100 101
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
102
# include "create_tasks.h"
103 104
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
105
#ifdef PDCP_USE_NETLINK
106 107
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
108
# endif
109 110
#endif

111 112 113
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
114 115
#endif

116
// In lte-enb.c
117
extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
118
extern void init_eNB(eNB_func_t);
119
extern void stop_eNB(void);
120
extern void kill_eNB_proc(void);
121

122
// In lte-ue.c
123 124
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
extern void fill_ue_band_info(void);
125 126
extern void init_UE(void);

127
#ifdef XFORMS
128
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
129
// at eNB 0, an UL scope for every UE
130
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
131
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
132
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
133
char title[255];
134
unsigned char                   scope_enb_num_ue = 2;
135 136
#endif //XFORMS

137

138

139 140


141

142 143
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
144
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
145

146

147 148


149

150

151
#ifdef XFORMS
152
static pthread_t                forms_thread; //xforms
153
#endif
154

155 156
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]
157

158

159
#if defined(ENABLE_ITTI)
160 161
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
162
#endif
163 164
volatile int                    oai_exit = 0;

165

166

167

168
static char                     UE_flag=0;
169 170
//static uint8_t                  eNB_id=0,UE_id=0;

171
static char                     threequarter_fs=0;
172

173
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
174
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
175

176
openair0_rf_map rf_map[MAX_NUM_CCs];
177

178
static char                    *conf_config_file_name = NULL;
179
#if defined(ENABLE_ITTI)
180
static char                    *itti_dump_file = NULL;
181 182
#endif

183
int UE_scan = 1;
184
int UE_scan_carrier = 0;
185 186
runmode_t mode = normal_txrx;

187 188
FILE *input_fd=NULL;

189

190 191
#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
192 193
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
194 195 196 197
#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
198
#endif
199

200 201


202
double sample_rate=30.72e6;
203
double bw = 10.0e6;
204

205
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
206

207 208
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
209
int chain_offset=0;
210
int phy_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
211

212

213 214 215
char ref[128] = "internal";
char channels[128] = "0";

216
int                      rx_input_level_dBm;
217
static int                      online_log_messages=0;
218
#ifdef XFORMS
219
extern int                      otg_enabled;
220
static char                     do_forms=0;
221
#else
222
int                             otg_enabled;
223
#endif
224
//int                             number_of_cards =   1;
225

226

227
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
228
eNB_func_t node_function=eNodeB_3GPP;
229

Florian Kaltenberger's avatar
Florian Kaltenberger committed
230
uint32_t target_dl_mcs = 28; //maximum allowed mcs
231
uint32_t target_ul_mcs = 20;
232
uint32_t timing_advance = 0;
233 234
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
235

236

237 238 239

extern void reset_opp_meas(void);
extern void print_opp_meas(void);
240
int transmission_mode=1;
241

242
int16_t           glog_level         = LOG_INFO;
243
int16_t           glog_verbosity     = LOG_MED;
244
int16_t           hw_log_level       = LOG_INFO;
245
int16_t           hw_log_verbosity   = LOG_MED;
246
int16_t           phy_log_level      = LOG_INFO;
247
int16_t           phy_log_verbosity  = LOG_MED;
248
int16_t           mac_log_level      = LOG_INFO;
249
int16_t           mac_log_verbosity  = LOG_MED;
250
int16_t           rlc_log_level      = LOG_INFO;
251
int16_t           rlc_log_verbosity  = LOG_MED;
252
int16_t           pdcp_log_level     = LOG_INFO;
253
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
254
int16_t           rrc_log_level      = LOG_INFO;
255
int16_t           rrc_log_verbosity  = LOG_MED;
256 257 258
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

259 260 261 262 263 264
# if defined(ENABLE_USE_MME)
int16_t           gtpu_log_level     = LOG_DEBUG;
int16_t           gtpu_log_verbosity = LOG_MED;
int16_t           udp_log_level      = LOG_DEBUG;
int16_t           udp_log_verbosity  = LOG_MED;
#endif
265 266 267
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
268
#endif
269

270 271 272

#ifdef ETHERNET
char *rrh_UE_ip = "127.0.0.1";
273
int rrh_UE_port = 51000;
274 275
#endif

276 277 278 279 280
/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

281 282 283 284
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

285
char uecap_xer[1024],uecap_xer_in=0;
286 287


288

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end)
{
    struct timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) {
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
	temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        temp.tv_sec = end.tv_sec-start.tv_sec;
	temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    }
    return temp;
}

Cedric Roux's avatar
Cedric Roux committed
307
void print_difftimes(void)
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
{
#ifdef DEBUG
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
    struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
    int             changed = 0;
    diff_time = clock_difftime(start, end);
    if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
    if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
#if 1
    if (changed) print_difftimes();
#endif
}

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

330
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
331
{
332
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
333 334 335
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
336
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
337 338
}

339
#if !defined(ENABLE_ITTI)
340 341 342 343 344 345 346 347
void signal_handler(int sig)
{
  void *array[10];
  size_t size;

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

349 350 351 352
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
353 354
  } else {
    printf("trying to exit gracefully...\n");
355
    oai_exit = 1;
356 357
  }
}
358
#endif
nikaeinn's avatar
nikaeinn committed
359 360 361 362 363 364 365 366 367 368 369
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

void help (void) {
  printf (KGRN "Usage:\n");
  printf("  sudo -E lte-softmodem [options]\n");
  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
  printf("Options:\n");
370
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
nikaeinn's avatar
nikaeinn committed
371 372 373 374
  printf("  --ulsch-max-errors set the max ULSCH erros\n");
  printf("  --calib-ue-rx set UE RX calibration\n");
  printf("  --calib-ue-rx-med \n");
  printf("  --calib-ue-rxbyp\n");
375 376
  printf("  --debug-ue-prach run normal prach power ramping, but don't continue random-access\n");
  printf("  --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n");
nikaeinn's avatar
nikaeinn committed
377
  printf("  --no-L2-connect bypass L2 and upper layers\n");
378 379 380 381
  printf("  --ue-rxgain set UE RX gain\n");
  printf("  --ue-txgain set UE TX gain\n");
  printf("  --ue-scan_carrier set UE to scan around carrier\n");
  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
382 383 384
  printf("  --RCC run using NGFI RCC node function\n");
  printf("  --RRU run using NGFI RRU node function\n");
  printf("  --eNB run using 3GPP eNB node function\n");   
385
  printf("  -C Set the downlink frequency for all component carriers\n");
nikaeinn's avatar
nikaeinn committed
386 387 388
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
389
  printf("  -G Set the global log verbosity \n");
nikaeinn's avatar
nikaeinn committed
390 391 392 393 394
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
kaltenbe's avatar
kaltenbe committed
395
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
nikaeinn's avatar
nikaeinn committed
396 397
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
398
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
nikaeinn's avatar
nikaeinn committed
399 400 401 402
  printf("  -U Set the lte softmodem as a UE\n");
  printf("  -W Enable L2 wireshark messages on localhost \n");
  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
  printf("  -x Set the transmission mode, valid options: 1 \n"RESET);    
403

nikaeinn's avatar
nikaeinn committed
404
}
405

406 407
void exit_fun(const char* s)
{
408
  if (s != NULL) {
409
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
410 411 412 413 414
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
415
  sleep(1); //allow lte-softmodem threads to exit first
416
  itti_terminate_tasks (TASK_UNKNOWN);
417
#endif
418 419 420

}

421

422
#ifdef XFORMS
423

424 425
void reset_stats(FL_OBJECT *button, long arg)
{
426 427
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
428 429 430

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
431 432 433 434
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
        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;
435
      }
436

437 438 439
      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;
440

441 442 443 444 445
      for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) {
        phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
446
      }
447
    }
448

449 450 451
    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;
452 453 454
  }
}

455 456
static void *scope_thread(void *arg)
{
457
  char stats_buffer[16384];
458
# ifdef ENABLE_XFORMS_WRITE_STATS
459
  FILE *UE_stats, *eNB_stats;
460
# endif
461
  int len = 0;
462
  struct sched_param sched_param;
463
  int UE_id, CC_id;
464
  int ue_cnt=0;
465

466
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
467
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
468

469
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
470

471
# ifdef ENABLE_XFORMS_WRITE_STATS
472 473

  if (UE_flag==1)
474
    UE_stats  = fopen("UE_stats.txt", "w");
475
  else
476
    eNB_stats = fopen("eNB_stats.txt", "w");
477

478
#endif
479

480 481
  while (!oai_exit) {
    if (UE_flag==1) {
482
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
483 484 485
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
486

487 488 489 490 491
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

492
    } else {
493 494 495 496 497 498
      if (PHY_vars_eNB_g[0][0]->mac_enabled==1) {
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
	fl_clear_browser(form_stats_l2->stats_text);
	fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
      }
499
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
500

501
      if (MAX_NUM_CCs>1)
502 503
        len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0);

kaltenbe's avatar
kaltenbe committed
504 505 506
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
507

508 509
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
510
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
511
	  if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
512
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
513 514 515 516
			  PHY_vars_eNB_g[0][CC_id],
			  UE_id);
	    ue_cnt++;
	  }
517
	}
518
      }
519

520
    }
521

522
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
523 524
    //usleep(100000); // 100 ms
    sleep(1);
525
  }
526

527
  //  printf("%s",stats_buffer);
528

529
# ifdef ENABLE_XFORMS_WRITE_STATS
530

531 532 533 534 535 536
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
537
  } else {
538 539 540 541 542 543
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
544

545
# endif
546

547
  pthread_exit((void*)arg);
548 549 550
}
#endif

551

552

553

554
#if defined(ENABLE_ITTI)
555
void *l2l1_task(void *arg)
556
{
557 558 559 560 561
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
562

563 564
  if (UE_flag == 0) {
    /* Wait for the initialize message */
565
    printf("Wait for the ITTI initialize message\n");
566 567 568 569 570
    do {
      if (message_p != NULL) {
        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
571

572
      itti_receive_msg (TASK_L2L1, &message_p);
573

574 575 576 577 578 579
      switch (ITTI_MSG_ID(message_p)) {
      case INITIALIZE_MESSAGE:
        /* Start eNB thread */
        LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
        start_eNB = 1;
        break;
580

581 582 583 584 585
      case TERMINATE_MESSAGE:
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
586

587 588 589 590 591
      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
      }
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
592

593 594 595
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }
596

597 598 599
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);
600

601 602 603 604 605
    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;
606

607 608 609
    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;
610

611 612 613
    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
614

615 616 617
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;
618

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

624 625 626
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  } while(!oai_exit);
627

628 629
  return NULL;
}
630
#endif
631

632

633

634 635


636

637

638

639

640 641
static void get_options (int argc, char **argv)
{
642 643 644
  int c;
  //  char                          line[1000];
  //  int                           l;
645
  int k,i;//,j,k;
646
#if defined(OAI_USRP) || defined(CPRIGW)
647
  int clock_src;
knopp's avatar
knopp committed
648
#endif
649
  int CC_id;
650 651


652 653

  const Enb_properties_array_t *enb_properties;
654

655 656
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
657
    LONG_OPTION_RF_CONFIG_FILE,
658 659 660 661 662
    LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
    LONG_OPTION_CALIB_UE_RX,
    LONG_OPTION_CALIB_UE_RX_MED,
    LONG_OPTION_CALIB_UE_RX_BYP,
    LONG_OPTION_DEBUG_UE_PRACH,
663
    LONG_OPTION_NO_L2_CONNECT,
664
    LONG_OPTION_CALIB_PRACH_TX,
665 666
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
667
    LONG_OPTION_SCANCARRIER,
668 669
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
670
    LONG_OPTION_LOOPMEMORY,
671 672 673 674
    LONG_OPTION_PHYTEST,
    LONG_OPTION_RCC,
    LONG_OPTION_RRU,
    LONG_OPTION_ENB
675
  };
676

677
  static const struct option long_options[] = {
678
    {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
679 680 681 682 683 684
    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
685 686 687 688
    {"calib-prach-tx",   no_argument,        NULL, LONG_OPTION_CALIB_PRACH_TX},
    {"ue-rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
    {"ue-txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
    {"ue-scan-carrier",   no_argument,  NULL, LONG_OPTION_SCANCARRIER},
689
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
690 691
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
692
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
693 694 695
    {"RCC", no_argument, NULL, LONG_OPTION_RCC},
    {"RRU", no_argument, NULL, LONG_OPTION_RRU},
    {"eNB", no_argument, NULL, LONG_OPTION_ENB},
696 697 698
    {NULL, 0, NULL, 0}
  };

699
  while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) {
700
    switch (c) {
701
    case LONG_OPTION_RF_CONFIG_FILE:
702 703 704 705 706 707
      if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) {
	printf("no configuration filename is provided\n");
      }
      else if (strlen(optarg)<=1024){
	strcpy(rf_config_file,optarg);
      }else {
708 709 710 711
         printf("Configuration filename is too long\n");
         exit(-1);   
      }
      break;
712 713 714 715
    case LONG_OPTION_MAXPOWER:
      tx_max_power[0]=atoi(optarg);
      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++)
	tx_max_power[CC_id]=tx_max_power[0];
716
      break;
717 718 719 720
    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
      ULSCH_max_consecutive_errors = atoi(optarg);
      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
      break;
721

722 723 724 725 726
    case LONG_OPTION_CALIB_UE_RX:
      mode = rx_calib_ue;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
      break;
727

728 729 730 731
    case LONG_OPTION_CALIB_UE_RX_MED:
      mode = rx_calib_ue_med;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
732
      break;
733

734 735 736 737 738
    case LONG_OPTION_CALIB_UE_RX_BYP:
      mode = rx_calib_ue_byp;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
      break;
739

740 741 742
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
743

744 745 746
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
747

748 749 750 751
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

752
    case LONG_OPTION_RXGAIN:
753 754
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
755

756
      break;
757

758 759 760
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
761

762
      break;
763

764 765 766 767 768
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

769 770 771 772 773 774
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

775 776 777 778
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
779 780 781
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
782 783 784 785 786 787 788 789 790 791 792 793

    case LONG_OPTION_RCC:
      node_function = NGFI_RCC_IF4;
      break;

    case LONG_OPTION_RRU:
      node_function = NGFI_RRU_IF4;
      break;

    case LONG_OPTION_ENB:
      node_function = eNodeB_3GPP;
      break;
794
      
795 796 797 798
    case 'A':
      timing_advance = atoi (optarg);
      break;

799
    case 'C':
800 801 802 803 804 805
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        downlink_frequency[CC_id][0] = atof(optarg); // 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];
        printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
knopp's avatar
knopp committed
806
      }
807

808
      UE_scan=0;
809

810
      break;
811

Florian Kaltenberger's avatar
Florian Kaltenberger committed
812 813 814 815
    case 'a':
      chain_offset = atoi(optarg);
      break;

816 817 818 819
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
820
#endif
821
      break;
822 823 824 825
      
    case 'E':
      threequarter_fs=1;
      break;
826

827 828 829
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
830
#else
831
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
832
#endif
833
      break;
834

835 836 837
    case 'O':
      conf_config_file_name = optarg;
      break;
838

839 840 841
    case 'U':
      UE_flag = 1;
      break;
842

843 844 845
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
846

847 848 849
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
850

851 852 853 854 855 856 857
    case 'W':
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      strncpy(in_ip, "127.0.0.1", sizeof(in_ip));
      in_ip[sizeof(in_ip) - 1] = 0; // terminate string
      printf("Enabling OPT for wireshark for local interface");
      /*
858 859 860
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
861
      } else {
862 863 864
      strncpy(in_ip, optarg, sizeof(in_ip));
      in_ip[sizeof(in_ip) - 1] = 0; // terminate string
      printf("Enabling OPT for wireshark with %s \n",in_ip);
865 866 867
      }
      */
      break;
868

869
    case 'P':
870 871
      opt_type = OPT_PCAP;
      opt_enabled=1;
872 873 874 875 876

      if (optarg == NULL) {
        strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap");
877
      } else {
878 879 880
        strncpy(in_path, optarg, sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
881
      }
882 883 884

      break;

885 886 887
    case 'V':
      ouput_vcd = 1;
      break;
888

889
    case  'q':
890 891
      opp_enabled = 1;
      break;
892

893 894 895
    case  'R' :
      online_log_messages =1;
      break;
896

897
    case 'r':
898
      UE_scan = 0;
899

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        switch(atoi(optarg)) {
        case 6:
          frame_parms[CC_id]->N_RB_DL=6;
          frame_parms[CC_id]->N_RB_UL=6;
          break;

        case 25:
          frame_parms[CC_id]->N_RB_DL=25;
          frame_parms[CC_id]->N_RB_UL=25;
          break;

        case 50:
          frame_parms[CC_id]->N_RB_DL=50;
          frame_parms[CC_id]->N_RB_UL=50;
          break;

        case 100:
          frame_parms[CC_id]->N_RB_DL=100;
          frame_parms[CC_id]->N_RB_UL=100;
          break;

        default:
          printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg));
          break;
        }
926
      }
927

928
      break;
929

930
    case 's':
931
#if defined(OAI_USRP) || defined(CPRIGW)
932 933

      clock_src = atoi(optarg);
934

935
      if (clock_src == 0) {
936 937 938 939 940
        //  char ref[128] = "internal";
        //strncpy(uhd_ref, ref, strlen(ref)+1);
      } else if (clock_src == 1) {
        //char ref[128] = "external";
        //strncpy(uhd_ref, ref, strlen(ref)+1);
941
      }
942

943 944 945 946
#else
      printf("Note: -s not defined for ExpressMIMO2\n");