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

39

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

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

#include "PHY/types.h"
46

47
#include "PHY/defs_eNB.h"
48
#include "common/ran_context.h"
49
#include "common/config/config_userapi.h"
oai's avatar
oai committed
50
#include "common/utils/load_module_shlib.h"
51
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
Raymond Knopp's avatar
 
Raymond Knopp committed
52
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
53

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

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

59 60 61
#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
62

63 64 65 66
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
67
#include "PHY/TOOLS/phy_scope_interface.h"
frtabu's avatar
frtabu committed
68
#include "nfapi/oai_integration/vendor_ext.h"
69 70 71 72
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
73
#include "common/utils/LOG/log.h"
Navid Nikaein's avatar
Navid Nikaein committed
74
#include "UTIL/OTG/otg_tx.h"
75
#include "UTIL/OTG/otg_externs.h"
76
#include "UTIL/MATH/oml.h"
77
#include "common/utils/LOG/vcd_signal_dumper.h"
78
#include "UTIL/OPT/opt.h"
79
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
80
//#include "PHY/TOOLS/time_meas.h"
81

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

86

87
#include "create_tasks.h"
88

89

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

92 93
#include "system.h"

94
#include "lte-softmodem.h"
oai's avatar
oai committed
95
#include "NB_IoT_interface.h"
96

frtabu's avatar
frtabu committed
97

98 99 100 101 102
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex


103 104
uint16_t sf_ahead=4;

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

110 111
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
112

113

Raymond Knopp's avatar
Raymond Knopp committed
114
volatile int             oai_exit = 0;
115

116
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
117
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
118

119
int UE_scan = 1;
120
int UE_scan_carrier = 0;
121
runmode_t mode = normal_txrx;
frtabu's avatar
frtabu committed
122

123 124
FILE *input_fd=NULL;

125

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

136
double rx_gain_off = 0.0;
137

Raymond Knopp's avatar
 
Raymond Knopp committed
138
double sample_rate=30.72e6;
139
double bw = 10.0e6;
140

141 142 143
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

144 145
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
146

Raymond Knopp's avatar
 
Raymond Knopp committed
147 148 149
char ref[128] = "internal";
char channels[128] = "0";

150 151
int rx_input_level_dBm;
int otg_enabled;
152

153
uint64_t num_missed_slots=0; // counter for the number of missed slots
154

155

156 157
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
158

159 160 161

extern void init_eNB_afterRU(void);

162
int transmission_mode=1;
163
int emulate_rf = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
164
int numerology = 0;
165

laurent's avatar
laurent committed
166
THREAD_STRUCT thread_struct;
167 168 169
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

170 171
double cpuf;

172
int oaisim_flag=0;
173
//threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1};
Raymond Knopp's avatar
 
Raymond Knopp committed
174

175 176 177
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

178 179 180 181 182
/*---------------------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 };

183
struct timespec clock_difftime(struct timespec start, struct timespec end) {
184
  struct timespec temp;
185

186 187 188 189 190 191 192
  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;
  }
193

194
  return temp;
195 196
}

197
void print_difftimes(void) {
198
#ifdef DEBUG
199
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
200
#else
201
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
202 203 204
#endif
}

205
void update_difftimes(struct timespec start, struct timespec end) {
206 207 208
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
209

210 211 212 213
  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;
  }
214

215 216 217 218
  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;
  }
219

220
#if 1
221

222
  if (changed) print_difftimes();
223

224 225 226 227 228
#endif
}

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

229
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
Raymond Knopp's avatar
 
Raymond Knopp committed
230
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
231
}
232
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
Raymond Knopp's avatar
 
Raymond Knopp committed
233
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
234 235
}

236

237
void exit_function(const char *file, const char *function, const int line, const char *s) {
238
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
239

240
  if (s != NULL) {
241
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
242
  }
243
  close_log_mem();
244
  oai_exit = 1;
245

246 247
  if (RC.ru == NULL)
    exit(-1); // likely init not completed, prevent crash or hang, exit now...
248

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

255 256 257 258 259
    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;
    }
  }
260

261 262
  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
263
}
264

265

266
static void get_options(void) {
267
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
268
  get_common_options(SOFTMODEM_ENB_BIT );
269
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
oai's avatar
oai committed
270

271
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
272 273 274 275 276 277
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    RCConfig();
    NB_eNB_INST = RC.nb_inst;
    printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);

278
    if (!IS_SOFTMODEM_NONBIOT) {
279 280 281 282 283 284 285 286
      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;
    }
  }
287 288 289
}


290

291

292

293
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
294 295 296
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
297
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
298 299 300 301 302 303 304 305 306 307
    /* 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;
308
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
    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;
324 325 326 327
    //    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
328
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
329
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
330 331 332
  }
}

333
void wait_RUs(void) {
334 335
  /* 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);
336 337
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
338

339 340
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
341
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
342 343
  }

344
  pthread_mutex_unlock(&RC.ru_mutex);
345 346 347
  LOG_I(PHY,"RUs configured\n");
}

348
void wait_eNBs(void) {
349 350 351 352
  int i,j;
  int waiting=1;

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

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

360 361 362 363 364
      for (j=0; j<RC.nb_L1_CC[i]; j++) {
        if (RC.eNB[i][j]->configured==0) {
          waiting=1;
          break;
        }
365 366
      }
    }
367
  }
368

369 370
  printf("eNB L1 are configured\n");
}
371

372

373 374
/*
 * helper function to terminate a certain ITTI task
375
 */
376
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) {
377
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
378
        itti_get_task_name(from), from, itti_get_task_name(to), to);
379
  MessageDef *msg;
380 381
  msg = itti_alloc_new_message (from, TERMINATE_MESSAGE);
  itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
382 383
}

384
extern void  free_transport(PHY_VARS_eNB *);
385
extern void  phy_free_RU(RU_t *);
386

387
int stop_L1L2(module_id_t enb_id) {
388 389
  LOG_W(ENB_APP, "stopping lte-softmodem\n");

390
  if (!RC.ru) {
391
    LOG_UI(ENB_APP, "no RU configured\n");
392 393 394
    return -1;
  }

395
  /* these tasks need to pick up new configuration */
396
  terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
Robert Schmidt's avatar
Robert Schmidt committed
397
  oai_exit = 1;
398
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
Robert Schmidt's avatar
Robert Schmidt committed
399
  kill_RU_proc(RC.ru[enb_id]);
400
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
401
  kill_eNB_proc(enb_id);
402
  oai_exit = 0;
403

404 405 406 407
  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]);
  }
408

409
  phy_free_RU(RC.ru[enb_id]);
410
  free_lte_top();
411 412 413 414
  return 0;
}

/*
415
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
416
 */
417
int restart_L1L2(module_id_t enb_id) {
418 419 420
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
421 422
  LOG_W(ENB_APP, "restarting lte-softmodem\n");
  /* block threads */
423
  pthread_mutex_lock(&sync_mutex);
424
  sync_var = -1;
425
  pthread_mutex_unlock(&sync_mutex);
426

427 428
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
429 430
  }

431 432 433 434 435
  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]);
436 437 438
  /* reset the list of connected UEs in the MAC, since in this process with
   * loose all UEs (have to reconnect) */
  init_UE_list(&RC.mac[enb_id]->UE_list);
439
  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
440

441 442 443 444 445 446 447
  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");
  }

448 449 450 451 452
  /* 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);
453 454
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
455 456 457 458 459 460
  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();
461 462 463 464 465 466
  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;
467 468
}

469 470 471 472
void init_pdcp(void) {
  if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
    pdcp_layer_init();
    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
473 474
                             (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;

475 476
    if (IS_SOFTMODEM_NOS1)
      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
477

478 479
    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT;

480 481 482
    pdcp_module_init(pdcp_initmask);

    if (NODE_IS_CU(RC.rrc[0]->node_type)) {
483
      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
484
    } else {
485 486
      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);
487 488
    }
  } else {
489
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
490 491
  }
}
492

493
static  void wait_nfapi_init(char *thread_name) {
494 495
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
496

497 498
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
499

500 501 502 503
  pthread_mutex_unlock(&nfapi_sync_mutex);
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

yilmazt's avatar
yilmazt committed
504 505
int main ( int argc, char **argv )
{
506
  int i;
507
  int CC_id = 0;
508
  int ru_id;
509
  int node_type = ngran_eNB;
510

511
  if ( load_configmodule(argc,argv,0) == NULL) {
512
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
513
  }
514

515
  mode = normal_txrx;
Raymond Knopp's avatar
 
Raymond Knopp committed
516
  set_latency_target();
517
  logInit();
518
  printf("Reading in command-line options\n");
519
  get_options ();
520

521
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
522

523
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
524 525
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
526
  }
Raymond Knopp's avatar
Raymond Knopp committed
527

528
#if T_TRACER
529
  T_Config_Init();
530
#endif
531 532
  //randominit (0);
  set_taus_seed (0);
533
  printf("configuring for RAU/RRU\n");
534

535
  if (opp_enabled ==1) {
536
    reset_opp_meas();
537
  }
538

539
  cpuf=get_cpu_freq_GHz();
540
  printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
Cedric Roux's avatar
Cedric Roux committed
541
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
542

543
  // initialize mscgen log after ITTI
544
  if (get_softmodem_params()->start_msc) {
545
    load_module_shlib("msc",NULL,0,&msc_interface);
546
  }
547

548
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
549
  init_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
550
  // to make a graceful exit when ctrl-c is pressed
551
  set_softmodem_sighandler();
Raymond Knopp's avatar
 
Raymond Knopp committed
552
  check_clock();
553 554 555 556
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
557
  printf("Runtime table\n");
558
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
559

560
  /* Read configuration */
561
  if (RC.nb_inst > 0) {
562
    read_config_and_init();
563 564 565 566 567 568 569 570 571 572 573 574 575
  } 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) {
    RCconfig_RU();
    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());
  }
576

577 578
  if (RC.nb_inst > 0) {
    /* Start the agent. If it is turned off in the configuration, it won't start */
579 580
    for (i = 0; i < RC.nb_inst; i++) {
      flexran_agent_start(i);
581
    }
582

583 584 585
    /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
     * for monolithic/F1 modes */
    init_pdcp();
586

587 588 589
    if (create_tasks(1) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1);
590
    }
591 592 593

    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
594
      RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
595
      itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
596
    }
597
    node_type = RC.rrc[0]->node_type;
598
  }
599

600
  if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
601 602 603 604 605
    protocol_ctxt_t ctxt;
    ctxt.module_id = 0 ;
    ctxt.instance = 0;
    ctxt.rnti = 0;
    ctxt.enb_flag = 1;
606 607
    ctxt.frame = 0;
    ctxt.subframe = 0;
608
    pdcp_run(&ctxt);
609
  }
610
    
611
  /* start threads if only L1 or not a CU */
612
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
613
    // init UE_PF_PO and mutex lock
Raymond Knopp's avatar
Raymond Knopp committed
614 615 616 617 618
    pthread_mutex_init(&ue_pf_po_mutex, NULL);
    memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
    mlockall(MCL_CURRENT | MCL_FUTURE);
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
619

Raymond Knopp's avatar
Raymond Knopp committed
620
    rt_sleep_ns(10*100000000ULL);
621
    
frtabu's avatar
frtabu committed
622 623
    if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
      LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
624 625 626
      pthread_cond_init(&sync_cond,NULL);
      pthread_mutex_init(&sync_mutex, NULL);
    }
627
    
frtabu's avatar
frtabu committed
628
    if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
629
#if defined(PRE_SCD_THREAD)
630
      init_ru_vnf();  // ru pointer is necessary for pre_scd.
631
#endif
Raymond Knopp's avatar
Raymond Knopp committed
632
      wait_nfapi_init("main?");
633
    }
634
    
frtabu's avatar
frtabu committed
635
    LOG_I(ENB_APP,"START MAIN THREADS\n");
Raymond Knopp's avatar
Raymond Knopp committed
636
    // start the main threads
637
    number_of_cards = 1;
638
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
639
    
640
    if (RC.nb_L1_inst > 0) {
641 642
      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);
643
      //      for (inst=0;inst<RC.nb_L1_inst;inst++)
644
      //  for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
645
    }
646
  }
647

648 649 650 651 652 653 654 655 656
  printf("wait_eNBs()\n");
  wait_eNBs();
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
  
  // 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");
657
    init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync);
658
    
659 660 661
    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);
662
    }
663
    
664
    config_sync_var=0;
665
    
frtabu's avatar
frtabu committed
666
    if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
667 668
      wait_nfapi_init("main?");
    }
669
    
670
    printf("wait RUs\n");
671
    // CI -- Flushing the std outputs for the previous marker to show on the eNB / RRU log file
672 673
    fflush(stdout);
    fflush(stderr);
674
    // end of CI modifications
675
    wait_RUs();
frtabu's avatar
frtabu committed
676
    LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU);
677
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
678 679
    printf("ALL RUs ready - init eNBs\n");

frtabu's avatar
frtabu committed
680 681
    if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) {
      LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n");
682
      init_eNB_afterRU();
683
    } else {
frtabu's avatar
frtabu committed
684
      LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n");
685
    }
686

frtabu's avatar
frtabu committed
687
    LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n");
Raymond Knopp's avatar
Raymond Knopp committed
688 689
    // connect the TX/RX buffers
    sleep(1); /* wait for thread activation */
frtabu's avatar
frtabu committed
690
    LOG_I(ENB_APP,"Sending sync to all threads\n");
Raymond Knopp's avatar
Raymond Knopp committed
691 692 693 694
    pthread_mutex_lock(&sync_mutex);
    sync_var=0;
    pthread_cond_broadcast(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
695
    config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
Raymond Knopp's avatar
Raymond Knopp committed
696
  }
697 698
  create_tasks_mbms(1);

699
  // wait for end of program
700
  LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
701 702 703 704
  // 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
705
  //getchar();
706 707
  if(IS_SOFTMODEM_DOFORMS)
     load_softscope("enb");
Raymond Knopp's avatar
 
Raymond Knopp committed
708
  itti_wait_tasks_end();
709
  oai_exit=1;
710
  LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
Raymond Knopp's avatar
 
Raymond Knopp committed
711
  // stop threads
712

713
  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
714 715
    if(IS_SOFTMODEM_DOFORMS)
      end_forms();
716

717
    LOG_I(ENB_APP,"stopping MODEM threads\n");
Robert Schmidt's avatar
Robert Schmidt committed
718
    stop_eNB(NB_eNB_INST);
719
    stop_RU(RC.nb_RU);
720

721 722 723 724
    /* 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++) {
725 726
	free_transport(RC.eNB[inst][cc_id]);
	phy_free_lte_eNB(RC.eNB[inst][cc_id]);
727 728
      }
    }
729

730
    for (int inst = 0; inst < RC.nb_RU; inst++) {
731 732
      phy_free_RU(RC.ru[inst]);
    }
733

734
    free_lte_top();
735
    end_configmodule();
Raymond Knopp's avatar
Raymond Knopp committed
736 737 738 739 740
    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);
741

742
    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
743
      if (RC.ru[ru_id]->rfdevice.trx_end_func) {
744 745
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
	RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
746
      }
frtabu's avatar
frtabu committed
747

748
      if (RC.ru[ru_id]->ifdevice.trx_end_func) {
749 750
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
	RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
751
      }
Raymond Knopp's avatar
Raymond Knopp committed
752
    }
Raymond Knopp's avatar
Raymond Knopp committed
753
  }
754
   
755
  terminate_opt();
Raymond Knopp's avatar
 
Raymond Knopp committed
756
  logClean();
757
  printf("Bye.\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
758 759
  return 0;
}