nr-softmodem.c 26.7 KB
Newer Older
Thomas Laurent's avatar
Thomas Laurent committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * 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
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * 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
 */


#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>


#include "T.h"

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include <common/utils/assertions.h>

#include "msc.h"

#include "PHY/types.h"
#include "common/ran_context.h"

#include "PHY/defs_gNB.h"
38
#include "PHY/defs_common.h"
Thomas Laurent's avatar
Thomas Laurent committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"

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

#include "PHY/phy_vars.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
#include "gnb_config.h"
55
#include "SIMULATION/TOOLS/sim.h"
Thomas Laurent's avatar
Thomas Laurent committed
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif

#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"

//#include "PHY/TOOLS/time_meas.h"

#ifndef OPENAIR2
  #include "UTIL/OTG/otg_vars.h"
#endif

72
#include "intertask_interface.h"
Thomas Laurent's avatar
Thomas Laurent committed
73
74
75
76
77

#include "PHY/INIT/phy_init.h"

#include "system.h"
#include <openair2/GNB_APP/gnb_app.h>
78
#include "PHY/TOOLS/phy_scope_interface.h"
79
80
#include "PHY/TOOLS/nr_phy_scope.h"
#include "stats.h"
Thomas Laurent's avatar
Thomas Laurent committed
81
#include "nr-softmodem.h"
82
83
#include "executables/softmodem-common.h"
#include "executables/thread-common.h"
Thomas Laurent's avatar
Thomas Laurent committed
84
#include "NB_IoT_interface.h"
85
#include "x2ap_eNB.h"
He Shanyun's avatar
He Shanyun committed
86
#include "ngap_gNB.h"
87
#include "gnb_paramdef.h"
88
#include <openair3/ocp-gtpu/gtp_itf.h>
Mahesh K's avatar
Mahesh K committed
89
#include "nfapi/oai_integration/vendor_ext.h"
Thomas Laurent's avatar
Thomas Laurent committed
90
91
92
93
94

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

Mahesh K's avatar
Mahesh K committed
95
extern uint8_t nfapi_mode; // Default to monolithic mode
Thomas Laurent's avatar
Thomas Laurent committed
96
THREAD_STRUCT thread_struct;
Thomas Laurent's avatar
Thomas Laurent committed
97
98
99
100
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
Thomas Laurent's avatar
Thomas Laurent committed
101
msc_interface_t msc_interface;
Thomas Laurent's avatar
Thomas Laurent committed
102

103
volatile int             start_gNB = 0;
Thomas Laurent's avatar
Thomas Laurent committed
104
105
106
107
volatile int             oai_exit = 0;

static int wait_for_sync = 0;

108
109
unsigned int mmapped_dma=0;
int single_thread_flag=1;
Thomas Laurent's avatar
Thomas Laurent committed
110

Thomas Laurent's avatar
Thomas Laurent committed
111
int8_t threequarter_fs=0;
Thomas Laurent's avatar
Thomas Laurent committed
112

113
uint64_t downlink_frequency[MAX_NUM_CCs][4];
114
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
Thomas Laurent's avatar
Thomas Laurent committed
115

116
//Temp fix for inexistent NR upper layer
Thomas Laurent's avatar
Thomas Laurent committed
117
118
119
120
121
122
unsigned char NB_gNB_INST = 1;


int UE_scan = 1;
int UE_scan_carrier = 0;
runmode_t mode = normal_txrx;
123
static double snr_dB=20;
Thomas Laurent's avatar
Thomas Laurent committed
124
125
126
127
128

FILE *input_fd=NULL;


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

double rx_gain_off = 0.0;

140
static int tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
Thomas Laurent's avatar
Thomas Laurent committed
141
142
143


int chain_offset=0;
144

Thomas Laurent's avatar
Thomas Laurent committed
145
146
147
148
149
150
151
152
153
154

uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;

char ref[128] = "internal";
char channels[128] = "0";

155
156
157
int rx_input_level_dBm;

int otg_enabled;
Thomas Laurent's avatar
Thomas Laurent committed
158

159
//int number_of_cards = 1;
Thomas Laurent's avatar
Thomas Laurent committed
160
161
162
163
164
165
166


//static NR_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
//static nfapi_nr_config_request_t *config[MAX_NUM_CCs];
uint32_t timing_advance = 0;
uint64_t num_missed_slots=0; // counter for the number of missed slots

Thomas Laurent's avatar
Thomas Laurent committed
167
168
169
170
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");
}
Thomas Laurent's avatar
Thomas Laurent committed
171
172
173
174
175

extern void reset_opp_meas(void);
extern void print_opp_meas(void);

extern void init_eNB_afterRU(void);
176
extern void *udp_eNB_task(void *args_p);
Thomas Laurent's avatar
Thomas Laurent committed
177
178
179
180
181

int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;

182

183
184
static char *parallel_config = NULL;
static char *worker_config = NULL;
Thomas Laurent's avatar
Thomas Laurent committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

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

openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

extern char uecap_xer[1024];
char uecap_xer_in=0;

/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;

/* forward declarations */
202
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
Thomas Laurent's avatar
Thomas Laurent committed
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
250
251
252
253
254
255
256
257
258
259
260
261

/*---------------------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));
}

262

Thomas Laurent's avatar
Thomas Laurent committed
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"


void exit_function(const char *file, const char *function, const int line, const char *s) {
  int ru_id;

  if (s != NULL) {
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
  }

  oai_exit = 1;

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

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

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

  sleep(1); //allow lte-softmodem threads to exit first
  exit(1);
}

298

Thomas Laurent's avatar
Thomas Laurent committed
299
300

int create_gNB_tasks(uint32_t gnb_nb) {
301
  LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb);
Thomas Laurent's avatar
Thomas Laurent committed
302
303
304
305
306
  itti_wait_ready(1);


  if (gnb_nb > 0) {
    /* Last task to create, others task must be ready before its start */
307
    /*if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
Thomas Laurent's avatar
Thomas Laurent committed
308
309
      LOG_E(GNB_APP, "Create task for gNB APP failed\n");
      return -1;
310
    }*/
311
    if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0){
zhenghuangkun's avatar
zhenghuangkun committed
312
313
      LOG_E(SCTP, "Create task for SCTP failed\n");
      return -1;
314
315
    }
    if (is_x2ap_enabled()) {
zhenghuangkun's avatar
zhenghuangkun committed
316
317
318
    if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0){
      LOG_E(X2AP, "Create task for X2AP failed\n");
    }
319
320
    }
    else {
zhenghuangkun's avatar
zhenghuangkun committed
321
      LOG_I(X2AP, "X2AP is disabled.\n");
322
    }
Thomas Laurent's avatar
Thomas Laurent committed
323
  }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  
  paramdef_t NETParams[]  =  GNBNETPARAMS_DESC;
  char aprefix[MAX_OPTNAME_SIZE*2 + 8];
  sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
  config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); 

  for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++){
    if( NETParams[i].strptr == NULL){
      LOG_E(NGAP, "No configuration in the file.\n");
	  NGAP_CONF_MODE = 0;
	}
    else {
      LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr);
    }
  
  }

Thomas Laurent's avatar
Thomas Laurent committed
341

342
  if (AMF_MODE_ENABLED && (get_softmodem_params()->phy_test==0 && get_softmodem_params()->do_ra==0 && get_softmodem_params()->sa==0)) {
343
    if (gnb_nb > 0) {
zhenghuangkun's avatar
zhenghuangkun committed
344
345
      /*
      if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
346
347
348
        LOG_E(SCTP, "Create task for SCTP failed\n");
        return -1;
      }
zhenghuangkun's avatar
zhenghuangkun committed
349
      */
350
351
352
353
354
355
356
      if(NGAP_CONF_MODE){
        if (itti_create_task (TASK_NGAP, ngap_gNB_task, NULL) < 0) {
          LOG_E(NGAP, "Create task for NGAP failed\n");
          return -1;
        }
      } else {
          LOG_E(NGAP, "Ngap task not created\n");
zhenghuangkun's avatar
zhenghuangkun committed
357
      }
Thomas Laurent's avatar
Thomas Laurent committed
358
359


360
361
362
      if(!emulate_rf){
        if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) {
          LOG_E(UDP_, "Create task for UDP failed\n");
363
          return -1;
Thomas Laurent's avatar
Thomas Laurent committed
364
        }
365
      }
Thomas Laurent's avatar
Thomas Laurent committed
366

367
      if (itti_create_task (TASK_GTPV1_U, &gtpv1u_gNB_task, NULL) < 0) {
368
369
370
        LOG_E(GTPU, "Create task for GTPV1U failed\n");
        return -1;
      }
371
    }
372
  }
373

Thomas Laurent's avatar
Thomas Laurent committed
374
375

  if (gnb_nb > 0) {
376
    if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
zhenghuangkun's avatar
zhenghuangkun committed
377
378
379
      LOG_E(GNB_APP, "Create task for gNB APP failed\n");
      return -1;
    }
Thomas Laurent's avatar
Thomas Laurent committed
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");

    if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
      LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
      return -1;
    }
  }

  return 0;
}


static void get_options(void) {


395
  paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ;
Thomas Laurent's avatar
Thomas Laurent committed
396

397
398
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
  get_common_options(SOFTMODEM_GNB_BIT );
399
  config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
400
401
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);

Thomas Laurent's avatar
Thomas Laurent committed
402
403
404
405
406
407
408
409
410



  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    memset((void *)&RC,0,sizeof(RC));
    /* Read RC configuration file */
    NRRCConfig();
    NB_gNB_INST = RC.nb_nr_inst;
    NB_RU   = RC.nb_RU;
411
    printf("Configuration: nb_rrc_inst %d, nb_nr_L1_inst %d, nb_ru %hhu\n",NB_gNB_INST,RC.nb_nr_L1_inst,NB_RU);
Thomas Laurent's avatar
Thomas Laurent committed
412
413
414
415
  }

  if(parallel_config != NULL) set_parallel_conf(parallel_config);

416
  if(worker_config != NULL) set_worker_conf(worker_config);
417

Thomas Laurent's avatar
Thomas Laurent committed
418
419
420
}


421
422
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs],
		             NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs])
423
424
{
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Thomas Laurent's avatar
Thomas Laurent committed
425
    frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS));
426
427
428
429
430
431
432
    config[CC_id] = (nfapi_nr_config_request_scf_t *) malloc(sizeof(nfapi_nr_config_request_scf_t));
    config[CC_id]->ssb_config.scs_common.value = 1;
    config[CC_id]->cell_config.frame_duplex_type.value = 1; //FDD
    //config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
    config[CC_id]->carrier_config.dl_grid_size[1].value = 106;
    config[CC_id]->carrier_config.ul_grid_size[1].value = 106;
    config[CC_id]->cell_config.phy_cell_id.value = 0;
Thomas Laurent's avatar
Thomas Laurent committed
433
434
435
436
437
438
439
440
441
442
443
    ///dl frequency to be filled in
    /*  //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;
444
        frame_parms[CC_id]->nb_antenna_ports_gNB  = 1;
Thomas Laurent's avatar
Thomas Laurent committed
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
        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;

    //    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];
        //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
        frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
    */
  }
}

void wait_RUs(void) {
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);

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

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

void wait_gNBs(void) {
Francesco Mani's avatar
Francesco Mani committed
489
  int i;
Thomas Laurent's avatar
Thomas Laurent committed
490
491
492
493
494
495
496
497
498
  int waiting=1;

  while (waiting==1) {
    printf("Waiting for gNB L1 instances to all get configured ... sleeping 50ms (nb_nr_sL1_inst %d)\n",RC.nb_nr_L1_inst);
    usleep(50*1000);
    waiting=0;

    for (i=0; i<RC.nb_nr_L1_inst; i++) {

499
500
501
      if (RC.gNB[i]->configured==0) {
	waiting=1;
	break;
Thomas Laurent's avatar
Thomas Laurent committed
502
503
504
505
506
507
508
509
510
511
512
      }
    }
  }

  printf("gNB L1 are configured\n");
}

/*
 * helper function to terminate a certain ITTI task
 */
void terminate_task(task_id_t task_id, module_id_t mod_id) {
513
  LOG_I(GNB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
Thomas Laurent's avatar
Thomas Laurent committed
514
  MessageDef *msg;
515
  msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE);
Thomas Laurent's avatar
Thomas Laurent committed
516
517
518
519
520
521
522
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}

//extern void  free_transport(PHY_VARS_gNB *);
extern void  nr_phy_free_RU(RU_t *);

int stop_L1L2(module_id_t gnb_id) {
523
  LOG_W(GNB_APP, "stopping nr-softmodem\n");
Thomas Laurent's avatar
Thomas Laurent committed
524
525
526
  oai_exit = 1;

  if (!RC.ru) {
527
    LOG_F(GNB_APP, "no RU configured\n");
Thomas Laurent's avatar
Thomas Laurent committed
528
529
530
531
532
533
534
    return -1;
  }

  /* stop trx devices, multiple carrier currently not supported by RU */
  if (RC.ru[gnb_id]) {
    if (RC.ru[gnb_id]->rfdevice.trx_stop_func) {
      RC.ru[gnb_id]->rfdevice.trx_stop_func(&RC.ru[gnb_id]->rfdevice);
535
      LOG_I(GNB_APP, "turned off RU rfdevice\n");
Thomas Laurent's avatar
Thomas Laurent committed
536
    } else {
537
      LOG_W(GNB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceeding anyway!\n");
Thomas Laurent's avatar
Thomas Laurent committed
538
539
540
541
    }

    if (RC.ru[gnb_id]->ifdevice.trx_stop_func) {
      RC.ru[gnb_id]->ifdevice.trx_stop_func(&RC.ru[gnb_id]->ifdevice);
542
      LOG_I(GNB_APP, "turned off RU ifdevice\n");
Thomas Laurent's avatar
Thomas Laurent committed
543
    } else {
544
      LOG_W(GNB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceeding anyway!\n");
Thomas Laurent's avatar
Thomas Laurent committed
545
546
    }
  } else {
547
    LOG_W(GNB_APP, "no RU found for index %d\n", gnb_id);
Thomas Laurent's avatar
Thomas Laurent committed
548
549
550
551
552
    return -1;
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, gnb_id);
553
  LOG_I(GNB_APP, "calling kill_gNB_proc() for instance %d\n", gnb_id);
Thomas Laurent's avatar
Thomas Laurent committed
554
  kill_gNB_proc(gnb_id);
555
  LOG_I(GNB_APP, "calling kill_NR_RU_proc() for instance %d\n", gnb_id);
556
  kill_NR_RU_proc(gnb_id);
Thomas Laurent's avatar
Thomas Laurent committed
557
558
  oai_exit = 0;

559
560
561
    //free_transport(RC.gNB[gnb_id]);
  phy_free_nr_gNB(RC.gNB[gnb_id]);

Thomas Laurent's avatar
Thomas Laurent committed
562
563
564
565
566
567
568
569
570
571
572
573

  nr_phy_free_RU(RC.ru[gnb_id]);
  free_lte_top();
  return 0;
}

/*
 * Restart the nr-softmodem after it has been soft-stopped with stop_L1L2()
 */
int restart_L1L2(module_id_t gnb_id) {
  RU_t *ru = RC.ru[gnb_id];
  MessageDef *msg_p = NULL;
574
  LOG_W(GNB_APP, "restarting nr-softmodem\n");
Thomas Laurent's avatar
Thomas Laurent committed
575
576
577
  /* block threads */
  sync_var = -1;

578
579
  RC.gNB[gnb_id]->configured = 0;
  
Thomas Laurent's avatar
Thomas Laurent committed
580
581
582

  RC.ru_mask |= (1 << ru->idx);
  set_function_spec_param(RC.ru[gnb_id]);
583
  LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
Thomas Laurent's avatar
Thomas Laurent committed
584
585
586
  // No more rrc thread, as many race conditions are hidden behind
  rrc_enb_init();
  itti_mark_task_ready(TASK_RRC_ENB);
Thomas Laurent's avatar
Thomas Laurent committed
587
588
589

  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
590
  msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ);
Thomas Laurent's avatar
Thomas Laurent committed
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
  RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[gnb_id]->configuration;
  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
  wait_gNBs();
  init_RU_proc(ru);
  ru->rf_map.card = 0;
  ru->rf_map.chain = 0; /* CC_id + chain_offset;*/
  wait_RUs();
  init_eNB_afterRU();
  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;
}

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

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

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

620
621
void init_pdcp(void) {
  //if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
Thomas Laurent's avatar
Thomas Laurent committed
622
623
624
  pdcp_layer_init();
  uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
                           (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
Guy De Souza's avatar
Guy De Souza committed
625

Thomas Laurent's avatar
Thomas Laurent committed
626
627
628
629
  if (IS_SOFTMODEM_NOS1) {
    printf("IS_SOFTMODEM_NOS1 option enabled \n");
    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
  }
630

Thomas Laurent's avatar
Thomas Laurent committed
631
  pdcp_module_init(pdcp_initmask);
632

Thomas Laurent's avatar
Thomas Laurent committed
633
634
635
636
637
638
  /*if (NODE_IS_CU(RC.rrc[0]->node_type)) {
    pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
  } else {*/
  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);
  //}
639
640
641
642
  /*} else {
    pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
  }*/
}
643

644

645
646
int main( int argc, char **argv )
{
Francesco Mani's avatar
Francesco Mani committed
647
  int ru_id, CC_id = 0;
Thomas Laurent's avatar
Thomas Laurent committed
648
649
650
  start_background_system();

  ///static configuration for NR at the moment
651
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) {
Thomas Laurent's avatar
Thomas Laurent committed
652
653
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }
654
  set_softmodem_sighandler();
Thomas Laurent's avatar
Thomas Laurent committed
655
656
657
658
659
660
661
662
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif
  mode = normal_txrx;
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
  logInit();
yilmazt's avatar
yilmazt committed
663
  configure_linux();
Thomas Laurent's avatar
Thomas Laurent committed
664
665
666
667
668
669
670
671
  printf("Reading in command-line options\n");
  get_options ();

  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
    fprintf(stderr,"Getting configuration failed\n");
    exit(-1);
  }

672
  openair0_cfg[0].threequarter_fs = threequarter_fs;
673
  AMF_MODE_ENABLED = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test;
674
  NGAP_CONF_MODE   = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test;
675

676
677
  if (get_softmodem_params()->do_ra)
    AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n");
678

679
680
681
  if (get_softmodem_params()->sa)
    AssertFatal(get_softmodem_params()->phy_test == 0,"Standalone mode and phy_test are mutually exclusive\n");

Thomas Laurent's avatar
Thomas Laurent committed
682
683
684
685
686
687
688
689
690
691
692
693
#if T_TRACER
  T_Config_Init();
#endif
  //randominit (0);
  set_taus_seed (0);
  printf("configuring for RAU/RRU\n");

  if (opp_enabled ==1) {
    reset_opp_meas();
  }

  cpuf=get_cpu_freq_GHz();
Laurent Thomas's avatar
Laurent Thomas committed
694
  itti_init(TASK_MAX, tasks_info);
Thomas Laurent's avatar
Thomas Laurent committed
695
  // initialize mscgen log after ITTI
696
  MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX);
697

Thomas Laurent's avatar
Thomas Laurent committed
698

Thomas Laurent's avatar
Thomas Laurent committed
699
  init_opt();
700

Thomas Laurent's avatar
Thomas Laurent committed
701
702

#ifdef PDCP_USE_NETLINK
703
if(!IS_SOFTMODEM_NOS1)
Thomas Laurent's avatar
Thomas Laurent committed
704
705
706
707
708
  netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
#endif
709

Thomas Laurent's avatar
Thomas Laurent committed
710
711
712
713
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
Cedric Roux's avatar
Cedric Roux committed
714
715

  if(IS_SOFTMODEM_NOS1)
Thomas Laurent's avatar
Thomas Laurent committed
716
    init_pdcp();
Cedric Roux's avatar
Cedric Roux committed
717

718
719
  if (RC.nb_nr_L1_inst > 0)
    RCconfig_NR_L1();
Thomas Laurent's avatar
Thomas Laurent committed
720
721
722
723
724
725
  if (RC.nb_nr_inst > 0)  {
    // don't create if node doesn't connect to RRC/S1/GTP
    AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n");
  }

  /* Start the agent. If it is turned off in the configuration, it won't start */
726
  /*
Thomas Laurent's avatar
Thomas Laurent committed
727
728
729
730
731
  RCconfig_nr_flexran();

  for (i = 0; i < RC.nb_nr_L1_inst; i++) {
    flexran_agent_start(i);
  }
732
*/
Thomas Laurent's avatar
Thomas Laurent committed
733
734
735
736
737
738
739
740

  // init UE_PF_PO and mutex lock
  pthread_mutex_init(&ue_pf_po_mutex, NULL);
  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
  mlockall(MCL_CURRENT | MCL_FUTURE);
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);

741
  usleep(1000);
Thomas Laurent's avatar
Thomas Laurent committed
742

743
  if (NFAPI_MODE) {
Thomas Laurent's avatar
Thomas Laurent committed
744
745
746
747
748
749
750
    printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
  }

  const char *nfapi_mode_str = "<UNKNOWN>";

751
  switch(NFAPI_MODE) {
Thomas Laurent's avatar
Thomas Laurent committed
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
    case 0:
      nfapi_mode_str = "MONOLITHIC";
      break;

    case 1:
      nfapi_mode_str = "PNF";
      break;

    case 2:
      nfapi_mode_str = "VNF";
      break;

    default:
      nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
      break;
  }

  printf("NFAPI MODE:%s\n", nfapi_mode_str);

Mahesh K's avatar
Mahesh K committed
771
  if (NFAPI_MODE==NFAPI_MODE_VNF)
Thomas Laurent's avatar
Thomas Laurent committed
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
    wait_nfapi_init("main?");

  printf("START MAIN THREADS\n");
  // start the main threads
  number_of_cards = 1;
  printf("RC.nb_nr_L1_inst:%d\n", RC.nb_nr_L1_inst);

  if (RC.nb_nr_L1_inst > 0) {
    printf("Initializing gNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
    init_gNB(single_thread_flag,wait_for_sync);
  }

  printf("wait_gNBs()\n");
  wait_gNBs();
  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);

  if (RC.nb_RU >0) {
    printf("Initializing RU threads\n");
790
    init_NR_RU(get_softmodem_params()->rf_config_file);
Thomas Laurent's avatar
Thomas Laurent committed
791
792
793
794
795
796
797
798
799

    for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
      RC.ru[ru_id]->rf_map.card=0;
      RC.ru[ru_id]->rf_map.chain=CC_id+chain_offset;
    }
  }

  config_sync_var=0;

Mahesh K's avatar
Mahesh K committed
800
  if (NFAPI_MODE==NFAPI_MODE_PNF) {
Thomas Laurent's avatar
Thomas Laurent committed
801
802
803
804
805
806
807
808
809
    wait_nfapi_init("main?");
  }

  printf("wait RUs\n");
  wait_RUs();
  printf("ALL RUs READY!\n");
  printf("RC.nb_RU:%d\n", RC.nb_RU);
  // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
  printf("ALL RUs ready - init gNBs\n");
810
  if(IS_SOFTMODEM_DOSCOPE) {
Thomas Laurent's avatar
Thomas Laurent committed
811
    sleep(1);	
812
813
814
    scopeParms_t p;
    p.argc=&argc;
    p.argv=argv;
Thomas Laurent's avatar
Thomas Laurent committed
815
816
    p.gNB=RC.gNB[0];
    p.ru=RC.ru[0];
817
    load_softscope("nr",&p);
818
819
  }

820
  if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
Thomas Laurent's avatar
Thomas Laurent committed
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
    printf("Not NFAPI mode - call init_eNB_afterRU()\n");
    init_eNB_afterRU();
  } else {
    printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
  }

  printf("ALL RUs ready - ALL gNBs ready\n");
  // connect the TX/RX buffers
  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);
  printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  end_configmodule();
  printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
  printf("Returned from ITTI signal handler\n");
  oai_exit=1;
  printf("oai_exit=%d\n",oai_exit);

  // stop threads
Thomas Laurent's avatar
Thomas Laurent committed
847
  /*#ifdef XFORMS
848

Thomas Laurent's avatar
Thomas Laurent committed
849
      printf("waiting for XFORMS thread\n");
Thomas Laurent's avatar
Thomas Laurent committed
850

Thomas Laurent's avatar
Thomas Laurent committed
851
852
853
854
      if (do_forms==1) {
        pthread_join(forms_thread,&status);
        fl_hide_form(form_stats->stats_form);
        fl_free_form(form_stats->stats_form);
Thomas Laurent's avatar
Thomas Laurent committed
855

Thomas Laurent's avatar
Thomas Laurent committed
856
857
          fl_hide_form(form_stats_l2->stats_form);
          fl_free_form(form_stats_l2->stats_form);
Thomas Laurent's avatar
Thomas Laurent committed
858

Thomas Laurent's avatar
Thomas Laurent committed
859
860
861
862
863
864
865
          for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        fl_hide_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
        fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
      }
          }
      }
866

Thomas Laurent's avatar
Thomas Laurent committed
867
  #endif*/
Thomas Laurent's avatar
Thomas Laurent committed
868
869
870
871
872
873
874
875
  printf("stopping MODEM threads\n");
  // cleanup
  stop_gNB(NB_gNB_INST);
  stop_RU(NB_RU);

  /* release memory used by the RU/gNB threads (incomplete), after all
   * threads have been stopped (they partially use the same memory) */
  for (int inst = 0; inst < NB_gNB_INST; inst++) {
876
877
      //free_transport(RC.gNB[inst]);
      phy_free_nr_gNB(RC.gNB[inst]);
Thomas Laurent's avatar
Thomas Laurent committed
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
  }

  for (int inst = 0; inst < NB_RU; inst++) {
    nr_phy_free_RU(RC.ru[inst]);
  }

  free_lte_top();
  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);

  // *** Handle per CC_id openair0

  for(ru_id=0; ru_id<NB_RU; ru_id++) {
    if (RC.ru[ru_id]->rfdevice.trx_end_func)
      RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);

    if (RC.ru[ru_id]->ifdevice.trx_end_func)
      RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
  }


  logClean();
  printf("Bye.\n");
  return 0;
}