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

22
/*! \file lte-softmodem.c
23
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
 
Raymond Knopp committed
25 26 27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
Raymond Knopp's avatar
 
Raymond Knopp committed
29 30 31
 * \note
 * \warning
 */
32

33

Cedric Roux's avatar
Cedric Roux committed
34 35 36
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

37
#include "rt_wrapper.h"
38
#include <common/utils/msc/msc.h>
39

40

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

43
#include "assertions.h"
44
#include "msc.h"
45 46

#include "PHY/types.h"
47

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

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

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

Laurent THOMAS's avatar
Laurent THOMAS committed
60 61
#include <openair1/PHY/phy_extern_ue.h>

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
#include "PHY/TOOLS/phy_scope_interface.h"
frtabu's avatar
frtabu committed
71
#include "nfapi/oai_integration/vendor_ext.h"
72 73 74 75
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
76
#include "common/utils/LOG/log.h"
Navid Nikaein's avatar
Navid Nikaein committed
77
#include "UTIL/OTG/otg_tx.h"
78
#include "UTIL/OTG/otg_externs.h"
79
#include "UTIL/MATH/oml.h"
80
#include "common/utils/LOG/vcd_signal_dumper.h"
81
#include "UTIL/OPT/opt.h"
82
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
83
//#include "PHY/TOOLS/time_meas.h"
84

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

89 90 91

#include "create_tasks.h"

92

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

95 96
#include "system.h"

97
#include "lte-softmodem.h"
oai's avatar
oai committed
98
#include "NB_IoT_interface.h"
laurent's avatar
laurent committed
99
#include <executables/split_headers.h>
100

frtabu's avatar
frtabu committed
101

102 103 104 105
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

106 107
uint16_t sf_ahead=4;

Raymond Knopp's avatar
 
Raymond Knopp committed
108 109
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
110
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
111
int config_sync_var=-1;
112

laurent's avatar
laurent committed
113 114 115 116
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
117
volatile int             oai_exit = 0;
118

119
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
120
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
121

122
int UE_scan = 1;
123
int UE_scan_carrier = 0;
124
runmode_t mode = normal_txrx;
frtabu's avatar
frtabu committed
125

126 127
FILE *input_fd=NULL;

128

129
#if MAX_NUM_CCs == 1
130
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
131 132
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
133 134 135 136
#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
137
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
138

139
double rx_gain_off = 0.0;
140

Raymond Knopp's avatar
 
Raymond Knopp committed
141
double sample_rate=30.72e6;
142
double bw = 10.0e6;
143

144 145 146
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

147 148
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
149

Raymond Knopp's avatar
 
Raymond Knopp committed
150 151 152
char ref[128] = "internal";
char channels[128] = "0";

laurent's avatar
laurent committed
153
int rx_input_level_dBm;
154
int otg_enabled;
laurent's avatar
laurent committed
155

156
uint64_t num_missed_slots=0; // counter for the number of missed slots
157

laurent's avatar
laurent committed
158 159 160 161 162 163 164
int split73=0;
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) {
  AssertFatal(false, "Must not be called in this context\n");
}
void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) {
  AssertFatal(false, "Must not be called in this context\n");
}
laurent's avatar
laurent committed
165

166 167
RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond);

laurent's avatar
laurent committed
168 169 170 171
extern void reset_opp_meas(void);
extern void print_opp_meas(void);


Raymond Knopp's avatar
Raymond Knopp committed
172 173
RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond);

174
int transmission_mode=1;
175
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
176
int numerology = 0;
177

laurent's avatar
laurent committed
178
THREAD_STRUCT thread_struct;
179 180
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;
laurent's avatar
laurent committed
181

182 183
double cpuf;

184
int oaisim_flag=0;
185
uint8_t proto_agent_flag = 0;
186

laurent's avatar
laurent committed
187

188 189 190
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

laurent's avatar
laurent committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
/*---------------------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;
}

void print_difftimes(void) {
#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
}

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

unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}


250
void exit_function(const char *file, const char *function, const int line, const char *s) {
251
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
252

253
  if (s != NULL) {
254
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
255
  }
256
  close_log_mem();
257
  oai_exit = 1;
258

259 260
  if (RC.ru == NULL)
    exit(-1); // likely init not completed, prevent crash or hang, exit now...
261

262 263 264 265
  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
    if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) {
      RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
      RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
266 267
    }

268 269 270 271 272
    if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
      RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
      RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
    }
  }
273

274 275
  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
276
}
277

laurent's avatar
laurent committed
278

279
static void get_options(void) {
280
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
281
  get_common_options(SOFTMODEM_ENB_BIT );
282
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
oai's avatar
oai committed
283

284
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
285 286 287 288
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    RCConfig();
    NB_eNB_INST = RC.nb_inst;
laurent's avatar
laurent committed
289
    printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
290

291
    if (!IS_SOFTMODEM_NONBIOT) {
292
      load_NB_IoT();
laurent's avatar
laurent committed
293
      printf("               nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
294 295 296 297 298 299
             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;
    }
  }
300 301
}

laurent's avatar
laurent committed
302 303 304 305




306
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
307 308 309
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
310
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
311 312 313 314 315 316 317 318 319 320
    /* 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;
321
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
    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;
337 338 339 340
    //    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
341
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
342
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
343 344 345
  }
}

346
void wait_RUs(void) {
347 348
  /* do not modify the following LOG_UI message, which is used by CI */
  LOG_UI(ENB_APP,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
349 350
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
351

352 353
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
354
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
355 356
  }

357
  pthread_mutex_unlock(&RC.ru_mutex);
358 359 360
  LOG_I(PHY,"RUs configured\n");
}

361
void wait_eNBs(void) {
362 363 364 365
  int i,j;
  int waiting=1;

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

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

373 374 375 376 377
      for (j=0; j<RC.nb_L1_CC[i]; j++) {
        if (RC.eNB[i][j]->configured==0) {
          waiting=1;
          break;
        }
378 379
      }
    }
380
  }
381

382 383
  printf("eNB L1 are configured\n");
}
384

385

386 387
/*
 * helper function to terminate a certain ITTI task
388
 */
389
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
390
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
391
        itti_get_task_name(from), from, itti_get_task_name(to), to);
392
  MessageDef *msg;
393
  msg = itti_alloc_new_message (from, 0, TERMINATE_MESSAGE);
394
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
395 396
}

397
extern void  free_transport(PHY_VARS_eNB *);
398
extern void  phy_free_RU(RU_t *);
399

400
int stop_L1L2(module_id_t enb_id) {
401 402
  LOG_W(ENB_APP, "stopping lte-softmodem\n");

403
  if (!RC.ru) {
404
    LOG_UI(ENB_APP, "no RU configured\n");
405 406 407
    return -1;
  }

408
  /* these tasks need to pick up new configuration */
409
  terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
Robert Schmidt's avatar
Robert Schmidt committed
410
  oai_exit = 1;
411
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
Robert Schmidt's avatar
Robert Schmidt committed
412
  kill_RU_proc(RC.ru[enb_id]);
413
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
414
  kill_eNB_proc(enb_id);
415
  oai_exit = 0;
416

417 418 419 420
  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]);
  }
421

422
  phy_free_RU(RC.ru[enb_id]);
423
  free_lte_top();
424 425 426 427
  return 0;
}

/*
428
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
429
 */
430
int restart_L1L2(module_id_t enb_id) {
431 432
  int cc_id;
  MessageDef *msg_p = NULL;
433 434
  LOG_W(ENB_APP, "restarting lte-softmodem\n");
  /* block threads */
435
  pthread_mutex_lock(&sync_mutex);
436
  sync_var = -1;
437
  pthread_mutex_unlock(&sync_mutex);
438

439 440
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
Raymond Knopp's avatar
Raymond Knopp committed
441 442 443 444 445
    for (int ru_id=0;ru_id<RC.eNB[enb_id][cc_id]->num_RU;ru_id++) {
      int ru_idx = RC.eNB[enb_id][cc_id]->RU_list[ru_id]->idx;
      RC.ru_mask |= (1 << ru_idx);
      set_function_spec_param(RC.ru[ru_idx]);
    }
446
  }
447 448
  /* reset the list of connected UEs in the MAC, since in this process with
   * loose all UEs (have to reconnect) */
449
  init_UE_info(&RC.mac[enb_id]->UE_info);
450
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
451

452 453 454 455 456 457
  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");
  }
458

459 460
  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
461
  msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
462 463
  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);
464 465
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
466
  wait_eNBs();
Raymond Knopp's avatar
Raymond Knopp committed
467 468 469 470 471 472 473 474 475
  for (int cc_id=0;cc_id<RC.nb_L1_CC[enb_id]; cc_id++) {
    for (int ru_id=0;ru_id<RC.eNB[enb_id][cc_id]->num_RU;ru_id++) {
      int ru_idx = RC.eNB[enb_id][cc_id]->RU_list[ru_id]->idx;

      init_RU_proc(RC.ru[ru_idx]);
      RC.ru[ru_idx]->rf_map.card = 0;
      RC.ru[ru_idx]->rf_map.chain = 0; /* CC_id + chain_offset;*/
    }
  }
476 477
  wait_RUs();
  init_eNB_afterRU();
478 479 480 481 482 483
  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;
484
}
485

486 487 488 489
void init_pdcp(void) {
  if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
    pdcp_layer_init();
    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
490 491
                             (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;

492 493
    if (IS_SOFTMODEM_NOS1)
      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
494

495 496
    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;

laurent's avatar
laurent committed
497
    pdcp_module_init(pdcp_initmask);
498 499

    if (NODE_IS_CU(RC.rrc[0]->node_type)) {
500
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
501
    } else {
502 503
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
      pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
504 505
    }
  } else {
506
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
507 508
  }
}
509

510
static  void wait_nfapi_init(char *thread_name) {
511 512
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
513

514 515
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
516

517
  pthread_mutex_unlock(&nfapi_sync_mutex);
518
  printf( "NFAPI: got sync (%s)\n", thread_name);
519 520
}

yilmazt's avatar
yilmazt committed
521 522
int main ( int argc, char **argv )
{
523
  int i;
524
  int CC_id = 0;
525
  int ru_id;
526
  int node_type = ngran_eNB;
527

laurent's avatar
laurent committed
528 529 530 531
  if ( load_configmodule(argc,argv,0) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }

532
  mode = normal_txrx;
laurent's avatar
laurent committed
533
  set_latency_target();
534
  logInit();
laurent's avatar
laurent committed
535
  printf("Reading in command-line options\n");
536
  get_options ();
537

538
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
539

laurent's avatar
laurent committed
540 541 542 543 544
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
  }

545
#if T_TRACER
546
  T_Config_Init();
547
#endif
548 549
  //randominit (0);
  set_taus_seed (0);
laurent's avatar
laurent committed
550
  printf("configuring for RAU/RRU\n");
551

laurent's avatar
laurent committed
552
  if (opp_enabled ==1) {
553
    reset_opp_meas();
laurent's avatar
laurent committed
554
  }
555

laurent's avatar
laurent committed
556 557
  cpuf=get_cpu_freq_GHz();
  printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
Laurent Thomas's avatar
Laurent Thomas committed
558
  itti_init(TASK_MAX, tasks_info);
laurent's avatar
laurent committed
559
  // allows to forward in wireshark L2 protocol for decoding
laurent's avatar
laurent committed
560 561 562 563 564
  // initialize mscgen log after ITTI
  if (get_softmodem_params()->start_msc) {
    load_module_shlib("msc",NULL,0,&msc_interface);
  }

565
  MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX);
566
  init_opt();
567 568
  // to make a graceful exit when ctrl-c is pressed
  set_softmodem_sighandler();
laurent's avatar
laurent committed
569 570 571 572 573 574 575 576
  check_clock();
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
  printf("Runtime table\n");
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);

577
  /* Read configuration */
578
  if (RC.nb_inst > 0) {
579
    read_config_and_init();
580 581 582 583 584 585 586 587
  } else {
    printf("RC.nb_inst = 0, Initializing L1\n");
    RCconfig_L1();
  }

  /* We need to read RU configuration before FlexRAN starts so it knows what
   * splits to report. Actual RU start comes later. */
  if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) {
Raymond Knopp's avatar
Raymond Knopp committed
588
    RC.ru = RCconfig_RU(RC.nb_RU,RC.nb_L1_inst,RC.eNB,&RC.ru_mask,&RC.ru_mutex,&RC.ru_cond);
589 590 591 592
    LOG_I(PHY,
          "number of L1 instances %d, number of RU %d, number of CPU cores %d\n",
          RC.nb_L1_inst, RC.nb_RU, get_nprocs());
  }
593

594
  if (RC.nb_inst > 0) {
595
    /* Start the agent. If it is turned off in the configuration, it won't start */
laurent's avatar
laurent committed
596
    for (i = 0; i < RC.nb_inst; i++) {
Mahesh's avatar
Mahesh committed
597
      if(NFAPI_MODE != NFAPI_MODE_PNF)
598
      flexran_agent_start(i);
laurent's avatar
laurent committed
599
    }
laurent's avatar
laurent committed
600
    
Mahesh's avatar
Mahesh committed
601 602
    /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
     * for monolithic/F1 modes */
603
   init_pdcp();
laurent's avatar
laurent committed
604
    
605 606 607
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
608
    }
609 610

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
611
      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
laurent's avatar
laurent committed
612 613
      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);
614
    }
615
    node_type = RC.rrc[0]->node_type;
616
  }
Raymond Knopp's avatar
Raymond Knopp committed
617

618
  if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
619 620 621 622 623
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
624 625
    ctxt.frame = 0;
    ctxt.subframe = 0;
626 627
    pdcp_run(&ctxt);
  }
laurent's avatar
laurent committed
628

629
  /* start threads if only L1 or not a CU */
630
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
631
    // init UE_PF_PO and mutex lock
Raymond Knopp's avatar
Raymond Knopp committed
632 633
    pthread_mutex_init(&ue_pf_po_mutex, NULL);
    memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
laurent's avatar
laurent committed
634
    mlockall(MCL_CURRENT | MCL_FUTURE);
Raymond Knopp's avatar
Raymond Knopp committed
635 636
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
frtabu's avatar
frtabu committed
637

Raymond Knopp's avatar
Raymond Knopp committed
638
    rt_sleep_ns(10*100000000ULL);
laurent's avatar
laurent committed
639

frtabu's avatar
frtabu committed
640 641
    if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
      LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
642 643 644
      pthread_cond_init(&sync_cond,NULL);
      pthread_mutex_init(&sync_mutex, NULL);
    }
laurent's avatar
laurent committed
645

frtabu's avatar
frtabu committed
646
    if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
647
#if defined(PRE_SCD_THREAD)
648
      init_ru_vnf();  // ru pointer is necessary for pre_scd.
649
#endif
Raymond Knopp's avatar
Raymond Knopp committed
650
      wait_nfapi_init("main?");
651
    }
laurent's avatar
laurent committed
652

frtabu's avatar
frtabu committed
653
    LOG_I(ENB_APP,"START MAIN THREADS\n");
Raymond Knopp's avatar
Raymond Knopp committed
654
    // start the main threads
655
    number_of_cards = 1;
656
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
laurent's avatar
laurent committed
657

658
    if (RC.nb_L1_inst > 0) {
659 660
      printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
      init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
Raymond Knopp's avatar
 
Raymond Knopp committed
661
    }
662 663 664
    for (int x=0; x < RC.nb_L1_inst; x++) 
      for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) {
        L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc;
665
        L1_rxtx_proc_t *L1proctx= &RC.eNB[x][CC_id]->proc.L1_proc_tx;
laurent's avatar
laurent committed
666 667 668
	L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t));
        L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
        L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
669
        if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 )
laurent's avatar
laurent committed
670
         initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true);
671
        else
laurent's avatar
laurent committed
672
         initTpool("n", L1proc->threadPool, true);
673 674 675 676 677
        initNotifiedFIFO(L1proc->respEncode);
        initNotifiedFIFO(L1proc->respDecode);
        L1proctx->threadPool=L1proc->threadPool;
        L1proctx->respEncode=L1proc->respEncode;
        L1proctx->nbEncode=L1proc->nbEncode;
678 679 680
    }


laurent's avatar
laurent committed
681
  }
laurent's avatar
laurent committed
682

laurent's avatar
laurent committed
683 684 685
  printf("wait_eNBs()\n");
  wait_eNBs();
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
686 687 688 689 690 691
  
  // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
  // but RU thread deals with pre_scd and this is necessary in VNF and simulator.
  // some initialization is necessary and init_ru_vnf do this.
  if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
    printf("Initializing RU threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
692
    init_RU(RC.ru,RC.nb_RU,RC.eNB,RC.nb_L1_inst,RC.nb_L1_CC,get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
693
    
694 695 696
    for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
      RC.ru[ru_id]->rf_map.card=0;
      RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
697
    }
laurent's avatar
laurent committed
698

699
    config_sync_var=0;
laurent's avatar
laurent committed
700

frtabu's avatar
frtabu committed
701
    if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
702 703
      wait_nfapi_init("main?");
    }
laurent's avatar
laurent committed
704

705
    printf("wait RUs\n");
706
    // end of CI modifications
laurent's avatar
laurent committed
707 708
    fflush(stdout);
    fflush(stderr);
laurent's avatar
laurent committed
709
    // wait_RUs() is wrong and over complex!
710
    wait_RUs();
frtabu's avatar
frtabu committed
711
    LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
712
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
laurent's avatar
laurent committed
713
    printf("ALL RUs ready - init eNBs\n");
laurent's avatar
laurent committed
714
    
frtabu's avatar
frtabu committed
715 716
    if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
717 718
      init_eNB_afterRU();
    } else {
frtabu's avatar
frtabu committed
719
      LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
720 721
    }

frtabu's avatar
frtabu committed
722
    LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
723 724
    // connect the TX/RX buffers
    sleep(1); /* wait for thread activation */
frtabu's avatar
frtabu committed
725
    LOG_I(ENB_APP,"Sending sync to all threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
726 727 728 729
    pthread_mutex_lock(&sync_mutex);
    sync_var=0;
    pthread_cond_broadcast(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
730
    create_tasks_mbms(1);
731
    config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
Raymond Knopp's avatar
Raymond Knopp committed
732
  }
733 734 735
  else
    create_tasks_mbms(1);
  //create_tasks_mbms(1);
736

737
  // wait for end of program
738
  LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
739 740 741 742
  // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
  fflush(stdout);
  fflush(stderr);
  // end of CI modifications
Raymond Knopp's avatar
 
Raymond Knopp committed
743
  //getchar();
744
  if(IS_SOFTMODEM_DOSCOPE)
745
     load_softscope("enb",NULL);
Raymond Knopp's avatar
 
Raymond Knopp committed
746
  itti_wait_tasks_end();
747
  oai_exit=1;
748
  LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
Raymond Knopp's avatar
 
Raymond Knopp committed
749
  // stop threads
750

751
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
752
    if(IS_SOFTMODEM_DOSCOPE)
753
      end_forms();
754

755
    LOG_I(ENB_APP,"stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
756
    stop_eNB(NB_eNB_INST);
757
    stop_RU(RC.nb_RU);
frtabu's avatar
frtabu committed
758

759 760 761 762
    /* 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++) {
laurent's avatar
laurent committed
763
	free_transport(RC.eNB[inst][cc_id]);
764 765 766
        phy_free_lte_eNB(RC.eNB[inst][cc_id]);
      }
    }
frtabu's avatar
frtabu committed
767

768
    for (int inst = 0; inst < RC.nb_RU; inst++) {
769 770
      phy_free_RU(RC.ru[inst]);
    }
frtabu's avatar
frtabu committed
771

772
    free_lte_top();
773
    end_configmodule();
Raymond Knopp's avatar
Raymond Knopp committed
774 775 776 777 778
    pthread_cond_destroy(&sync_cond);
    pthread_mutex_destroy(&sync_mutex);
    pthread_cond_destroy(&nfapi_sync_cond);
    pthread_mutex_destroy(&nfapi_sync_mutex);
    pthread_mutex_destroy(&ue_pf_po_mutex);
frtabu's avatar
frtabu committed
779

780
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
781
      if (RC.ru[ru_id]->rfdevice.trx_end_func) {
laurent's avatar
laurent committed
782 783
        RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
784
      }
frtabu's avatar
frtabu committed
785

786
      if (RC.ru[ru_id]->ifdevice.trx_end_func) {
laurent's avatar
laurent committed
787 788
        RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
789
      }
Raymond Knopp's avatar
Raymond Knopp committed
790
    }
Raymond Knopp's avatar
Raymond Knopp committed
791
  }
laurent's avatar
laurent committed
792

793
  terminate_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
794
  logClean();
795
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
796 797
  return 0;
}