oaisim_functions.c 66.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * 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.0  (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
 */
21

22
23
24
25
26
27
28
29
30
31
/*! \file oaisim_functions.c
* \brief function primitives of oaisim
* \author Navid Nikaein 
* \date 2013-2015
* \version 1.0
* \company Eurecom
* \email: openair_tech@eurecom.fr
* \note
* \warning
*/
32
33


34
35
36
37
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
38
#include <execinfo.h>
39
#include <time.h>
gauthier's avatar
gauthier committed
40
#include <mcheck.h>
41
#include <sys/timerfd.h>
42

43
#include "assertions.h"
44
45
46
47
#include "oaisim_functions.h"

#include "PHY/extern.h"
#include "LAYER2/MAC/extern.h"
48
49
#ifdef OPENAIR2
#include "LAYER2/MAC/proto.h"
50
#endif
51
52
53
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
#include "LAYER2/PDCP_v10.1.0/pdcp_primitives.h"
#include "RRC/LITE/extern.h"
Cedric Roux's avatar
Cedric Roux committed
54
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
55
#include "PHY_INTERFACE/extern.h"
56
//#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
57
#include "SCHED/extern.h"
Cedric Roux's avatar
Cedric Roux committed
58
#include "SIMULATION/ETH_TRANSPORT/proto.h"
59
60
61
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
62
#include "UTIL/OTG/otg_config.h"
winckel's avatar
winckel committed
63
#include "UTIL/OTG/otg_tx.h"
64
#if ENABLE_RAL
65
66
#include "lteRALenb.h"
#include "lteRALue.h"
gauthier's avatar
gauthier committed
67
#endif
68

Cedric Roux's avatar
Cedric Roux committed
69
#include "cor_SF_sim.h"
70
#include "enb_config.h"
Cedric Roux's avatar
Cedric Roux committed
71

72
73
74
75
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

76
77
78
79
#if defined(ENABLE_USE_MME)
# include "s1ap_eNB.h"
#endif

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

83
#ifdef SMBV
gauthier's avatar
gauthier committed
84
extern uint8_t config_smbv;
85
86
87
88
89
90
91
92
93
extern char smbv_ip[16];
#endif

//constant for OAISIM soft realtime calibration
#define SF_DEVIATION_OFFSET_NS 100000 //= 0.1ms : should be as a number of UE
#define SLEEP_STEP_US       100 //  = 0.01ms could be adaptive, should be as a number of UE
#define K 2                  // averaging coefficient
#define TARGET_SF_TIME_NS 1000000       // 1ms = 1000000 ns

94
95
#define min(a,b) ((a)<(b)?(a):(b))

gauthier's avatar
gauthier committed
96
97
98
99
int           otg_times             = 0;
int           if_times              = 0;
int           for_times             = 0;

gauthier's avatar
gauthier committed
100
uint16_t           Nid_cell              = 0; //needed by init_lte_vars
101
int           nb_antennas_rx_ue        = 1; // //
102
uint8_t            target_dl_mcs         = 16; // max mcs used by MAC scheduler
gauthier's avatar
gauthier committed
103
uint8_t            rate_adaptation_flag  = 0;
104
uint8_t        set_snr         = 0;
gauthier's avatar
gauthier committed
105
uint8_t            set_sinr              = 0;
106
double             snr_dB=0, sinr_dB=0;
gauthier's avatar
gauthier committed
107
108
109
110
uint8_t            set_seed              = 0;
uint8_t            cooperation_flag;          // for cooperative communication
uint8_t            abstraction_flag      = 0;
uint8_t            ethernet_flag         = 0;
gauthier's avatar
gauthier committed
111
double        snr_step              = 1.0;
gauthier's avatar
gauthier committed
112
uint8_t            ue_connection_test    = 0;
gauthier's avatar
gauthier committed
113
double        forgetting_factor     = 0.0;
gauthier's avatar
gauthier committed
114
115
116
uint8_t            beta_ACK              = 0;
uint8_t            beta_RI               = 0;
uint8_t            beta_CQI              = 2;
117
uint8_t            target_ul_mcs         = 16;
knopp's avatar
   
knopp committed
118
LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
gauthier's avatar
gauthier committed
119
120
int           map1,map2;
double      **ShaF                  = NULL;
121
// pointers signal buffers (s = transmit, r,r0 = receive)
gauthier's avatar
gauthier committed
122
double      **s_re, **s_im, **r_re, **r_im, **r_re0, **r_im0;
123
124
node_list*     ue_node_list          = NULL;
node_list*     enb_node_list         = NULL;
125
int           omg_period            = 10000;
126
int           pdcp_period           = 0;
127
int           cba_backoff           = 30;
128
129
// time calibration for soft realtime mode
struct timespec time_spec;
gauthier's avatar
gauthier committed
130
131
132
133
134
unsigned long   time_last           = 0;
unsigned long   time_now            = 0;
int             td                  = 0;
int             td_avg              = 0;
int             sleep_time_us       = 0;
135

Florian Kaltenberger's avatar
Florian Kaltenberger committed
136
137
int phy_test = 0;

138
139
140
141
#ifdef OPENAIR2
// omv related info
//pid_t omv_pid;
char full_name[200];
142
extern int pfd[2]; // fd for omv : fixme: this could be a local var
143
144
145
146
147
148
149
150
151
152
153
154
155
char fdstr[10];
char frames[10];
char num_enb[10];
char num_ue[10];
//area_x, area_y and area_z for omv
char x_area[20];
char y_area[20];
char z_area[20];
char nb_antenna[20];
char frame_type[10];
char tdd_config[10];
#endif

gauthier's avatar
gauthier committed
156
Packet_OTG_List_t *otg_pdcp_buffer = NULL;
157
158
159

extern node_desc_t *enb_data[NUMBER_OF_eNB_MAX];
extern node_desc_t *ue_data[NUMBER_OF_UE_MAX];
knopp's avatar
   
knopp committed
160
161
extern channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
extern channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
162
163

extern mapping small_scale_names[];
gauthier's avatar
gauthier committed
164
165
166
167
#if defined(Rel10)
extern pdcp_mbms_t pdcp_mbms_array_ue[NUMBER_OF_UE_MAX][maxServiceCount][maxSessionPerPMCH];
extern pdcp_mbms_t pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][maxServiceCount][maxSessionPerPMCH];
#endif
168

169
170
extern time_stats_t dl_chan_stats;
extern time_stats_t ul_chan_stats;
171

172
173
extern int xforms;

174

175
176
177
extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];

178
179
180
eth_params_t *eth_params;

void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int,int);
181
182
void stop_eNB(int nb_inst);

183
184
const Enb_properties_array_t *enb_properties;

185
int oaisim_flag=1;
186

187
188
void get_simulation_options(int argc, char *argv[])
{
winckel's avatar
winckel committed
189
  int                           option;
190
  char  *conf_config_file_name = NULL;
winckel's avatar
winckel committed
191

winckel's avatar
winckel committed
192
  enum long_option_e {
gauthier's avatar
gauthier committed
193
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
winckel's avatar
winckel committed
194

gauthier's avatar
gauthier committed
195
    LONG_OPTION_ENB_CONF,
winckel's avatar
winckel committed
196

gauthier's avatar
gauthier committed
197
198
    LONG_OPTION_PDNC_PERIOD,
    LONG_OPTION_OMG_PERIOD,
199
    LONG_OPTION_OEH_ENABLED,
winckel's avatar
winckel committed
200

gauthier's avatar
gauthier committed
201
202
203
204
    LONG_OPTION_ENB_RAL_LISTENING_PORT,
    LONG_OPTION_ENB_RAL_IP_ADDRESS,
    LONG_OPTION_ENB_RAL_LINK_ID,
    LONG_OPTION_ENB_RAL_LINK_ADDRESS,
winckel's avatar
winckel committed
205

gauthier's avatar
gauthier committed
206
207
208
    LONG_OPTION_ENB_MIHF_REMOTE_PORT,
    LONG_OPTION_ENB_MIHF_IP_ADDRESS,
    LONG_OPTION_ENB_MIHF_ID,
winckel's avatar
winckel committed
209

gauthier's avatar
gauthier committed
210
211
212
213
    LONG_OPTION_UE_RAL_LISTENING_PORT,
    LONG_OPTION_UE_RAL_IP_ADDRESS,
    LONG_OPTION_UE_RAL_LINK_ID,
    LONG_OPTION_UE_RAL_LINK_ADDRESS,
winckel's avatar
winckel committed
214

gauthier's avatar
gauthier committed
215
216
217
    LONG_OPTION_UE_MIHF_REMOTE_PORT,
    LONG_OPTION_UE_MIHF_IP_ADDRESS,
    LONG_OPTION_UE_MIHF_ID,
gauthier's avatar
gauthier committed
218
219

    LONG_OPTION_MALLOC_TRACE_ENABLED,
220
221

    LONG_OPTION_CBA_BACKOFF_TIMER,
222

Florian Kaltenberger's avatar
Florian Kaltenberger committed
223
    LONG_OPTION_PHYTEST,
224
    LONG_OPTION_XFORMS,
Cedric Roux's avatar
Cedric Roux committed
225
226
227
228

#if T_TRACER
    LONG_OPTION_T_PORT,
    LONG_OPTION_T_NOWAIT,
229
    LONG_OPTION_T_DONT_FORK,
Cedric Roux's avatar
Cedric Roux committed
230
#endif
winckel's avatar
winckel committed
231
  };
winckel's avatar
winckel committed
232

winckel's avatar
winckel committed
233
  static struct option long_options[] = {
234
    {"enb-conf",               required_argument, 0, LONG_OPTION_ENB_CONF},
winckel's avatar
winckel committed
235

236
237
238
    {"pdcp-period",            required_argument, 0, LONG_OPTION_PDNC_PERIOD},
    {"omg-period",             required_argument, 0, LONG_OPTION_OMG_PERIOD},
    {"oeh-enabled",            no_argument, 0, LONG_OPTION_OEH_ENABLED},
winckel's avatar
winckel committed
239

240
241
242
243
    {"enb-ral-listening-port", required_argument, 0, LONG_OPTION_ENB_RAL_LISTENING_PORT},
    {"enb-ral-ip-address",     required_argument, 0, LONG_OPTION_ENB_RAL_IP_ADDRESS},
    {"enb-ral-link-id",        required_argument, 0, LONG_OPTION_ENB_RAL_LINK_ID},
    {"enb-ral-link-address",   required_argument, 0, LONG_OPTION_ENB_RAL_LINK_ADDRESS},
winckel's avatar
winckel committed
244

245
246
247
    {"enb-mihf-remote-port",   required_argument, 0, LONG_OPTION_ENB_MIHF_REMOTE_PORT},
    {"enb-mihf-ip-address",    required_argument, 0, LONG_OPTION_ENB_MIHF_IP_ADDRESS},
    {"enb-mihf-id",            required_argument, 0, LONG_OPTION_ENB_MIHF_ID},
winckel's avatar
winckel committed
248

249
250
251
252
    {"ue-ral-listening-port",  required_argument, 0, LONG_OPTION_UE_RAL_LISTENING_PORT},
    {"ue-ral-ip-address",      required_argument, 0, LONG_OPTION_UE_RAL_IP_ADDRESS},
    {"ue-ral-link-id",         required_argument, 0, LONG_OPTION_UE_RAL_LINK_ID},
    {"ue-ral-link-address",    required_argument, 0, LONG_OPTION_UE_RAL_LINK_ADDRESS},
winckel's avatar
winckel committed
253

254
255
256
    {"ue-mihf-remote-port",    required_argument, 0, LONG_OPTION_UE_MIHF_REMOTE_PORT},
    {"ue-mihf-ip-address",     required_argument, 0, LONG_OPTION_UE_MIHF_IP_ADDRESS},
    {"ue-mihf-id",             required_argument, 0, LONG_OPTION_UE_MIHF_ID},
257

258
    {"malloc-trace-enabled",   no_argument,       0, LONG_OPTION_MALLOC_TRACE_ENABLED},
259

260
    {"cba-backoff",            required_argument, 0, LONG_OPTION_CBA_BACKOFF_TIMER},
261

Florian Kaltenberger's avatar
Florian Kaltenberger committed
262
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
263
    {"xforms",                 no_argument,       0, LONG_OPTION_XFORMS},
Florian Kaltenberger's avatar
Florian Kaltenberger committed
264

Cedric Roux's avatar
Cedric Roux committed
265
266
267
#if T_TRACER
    {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
    {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
268
    {"T_dont_fork",            no_argument,       0, LONG_OPTION_T_DONT_FORK},
Cedric Roux's avatar
Cedric Roux committed
269
270
#endif

271
    {NULL, 0, NULL, 0}
winckel's avatar
winckel committed
272
  };
winckel's avatar
winckel committed
273

274
  while ((option = getopt_long (argc, argv, "aA:b:B:c:C:D:d:eE:f:FGg:hHi:IJ:j:k:K:l:L:m:M:n:N:oO:p:P:qQ:rR:s:S:t:T:u:U:vV:w:W:x:X:y:Y:z:Z:", long_options, NULL)) != -1) {
275
    switch (option) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
276
277
278
279
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;

280
281
282
283
284
285
    case LONG_OPTION_ENB_CONF:
      if (optarg) {
        free(conf_config_file_name); // prevent memory leak if option is used multiple times
        conf_config_file_name = strdup(optarg);
        printf("eNB configuration file is %s\n", conf_config_file_name);
      }
winckel's avatar
winckel committed
286

287
      break;
winckel's avatar
winckel committed
288

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    case LONG_OPTION_PDNC_PERIOD:
      if (optarg) {
        pdcp_period = atoi(optarg);
        printf("PDCP period is %d\n", pdcp_period);
      }

      break;

    case LONG_OPTION_OMG_PERIOD:
      if (optarg) {
        omg_period = atoi(optarg);
        printf("OMG period is %d\n", omg_period);
      }

      break;

    case LONG_OPTION_OEH_ENABLED:
      oai_emulation.info.oeh_enabled = 1;
      break;

    case LONG_OPTION_MALLOC_TRACE_ENABLED:
      mtrace();
      break;

    case LONG_OPTION_CBA_BACKOFF_TIMER:
      oai_emulation.info.cba_backoff=atoi(optarg);
      cba_backoff=atoi(optarg);
      printf("setting CBA backoff to %d\n", cba_backoff);
      break;
gauthier's avatar
gauthier committed
318

319
#if ENABLE_RAL
winckel's avatar
winckel committed
320

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
    case LONG_OPTION_ENB_RAL_LISTENING_PORT:
      if (optarg) {
        g_conf_enb_ral_listening_port = strdup(optarg);
        printf("eNB RAL listening port is %s\n", g_conf_enb_ral_listening_port);
      }

      break;

    case LONG_OPTION_ENB_RAL_IP_ADDRESS:
      if (optarg) {
        g_conf_enb_ral_ip_address = strdup(optarg);
        printf("eNB RAL IP address is %s\n", g_conf_enb_ral_ip_address);
      }

      break;

    case LONG_OPTION_ENB_RAL_LINK_ADDRESS:
      if (optarg) {
        g_conf_enb_ral_link_address = strdup(optarg);
        printf("eNB RAL link address is %s\n", g_conf_enb_ral_link_address);
      }

      break;

    case LONG_OPTION_ENB_RAL_LINK_ID:
      if (optarg) {
        g_conf_enb_ral_link_id = strdup(optarg);
        printf("eNB RAL link id is %s\n", g_conf_enb_ral_link_id);
      }

      break;

    case LONG_OPTION_ENB_MIHF_REMOTE_PORT:
      if (optarg) {
        g_conf_enb_mihf_remote_port = strdup(optarg);
        printf("eNB MIH-F remote port is %s\n", g_conf_enb_mihf_remote_port);
      }

      break;

    case LONG_OPTION_ENB_MIHF_IP_ADDRESS:
      if (optarg) {
        g_conf_enb_mihf_ip_address = strdup(optarg);
        printf("eNB MIH-F IP address is %s\n", g_conf_enb_mihf_ip_address);
      }

      break;

    case LONG_OPTION_ENB_MIHF_ID:
      if (optarg) {
        g_conf_enb_mihf_id = strdup(optarg);
        printf("eNB MIH-F id is %s\n", g_conf_enb_mihf_id);
      }

      break;

    case LONG_OPTION_UE_RAL_LISTENING_PORT:
      if (optarg) {
        g_conf_ue_ral_listening_port = strdup(optarg);
        printf("UE RAL listening port is %s\n", g_conf_ue_ral_listening_port);
      }

      break;

    case LONG_OPTION_UE_RAL_IP_ADDRESS:
      if (optarg) {
        g_conf_ue_ral_ip_address = strdup(optarg);
        printf("UE RAL IP address is %s\n", g_conf_ue_ral_ip_address);
      }

      break;

    case LONG_OPTION_UE_RAL_LINK_ID:
      if (optarg) {
        g_conf_ue_ral_link_id = strdup(optarg);
        printf("UE RAL link id is %s\n", g_conf_ue_ral_link_id);
      }

      break;

    case LONG_OPTION_UE_RAL_LINK_ADDRESS:
      if (optarg) {
        g_conf_ue_ral_link_address = strdup(optarg);
        printf("UE RAL link address is %s\n", g_conf_ue_ral_link_address);
      }

      break;

    case LONG_OPTION_UE_MIHF_REMOTE_PORT:
      if (optarg) {
        g_conf_ue_mihf_remote_port = strdup(optarg);
        printf("UE MIH-F remote port is %s\n", g_conf_ue_mihf_remote_port);
      }

      break;

    case LONG_OPTION_UE_MIHF_IP_ADDRESS:
      if (optarg) {
        g_conf_ue_mihf_ip_address = strdup(optarg);
        printf("UE MIH-F IP address is %s\n", g_conf_ue_mihf_ip_address);
      }

      break;

    case LONG_OPTION_UE_MIHF_ID:
      if (optarg) {
        g_conf_ue_mihf_id = strdup(optarg);
        printf("UE MIH-F id is %s\n", g_conf_ue_mihf_id);
      }

      break;
432
#endif
433

434
435
436
437
    case LONG_OPTION_XFORMS:
      xforms=1;
      break;

Cedric Roux's avatar
Cedric Roux committed
438
439
440
441
442
443
444
445
446
447
448
449
450
#if T_TRACER
    case LONG_OPTION_T_PORT: {
      extern int T_port;
      if (optarg == NULL) abort();  /* should not happen */
      T_port = atoi(optarg);
      break;
    }

    case LONG_OPTION_T_NOWAIT: {
      extern int T_wait;
      T_wait = 0;
      break;
    }
451
452
453
454
455
456

    case LONG_OPTION_T_DONT_FORK: {
      extern int T_dont_fork;
      T_dont_fork = 1;
      break;
    }
Cedric Roux's avatar
Cedric Roux committed
457
458
#endif

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
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
    case 'a':
      abstraction_flag = 1;
      break;

    case 'A':

      //oai_emulation.info.ocm_enabled=1;
      if (optarg == NULL)
        oai_emulation.environment_system_config.fading.small_scale.selected_option="AWGN";
      else
        oai_emulation.environment_system_config.fading.small_scale.selected_option= optarg;

      //awgn_flag = 1;
      break;

    case 'b':
      oai_emulation.info.nb_enb_local = atoi (optarg);
      break;

    case 'B':
      oai_emulation.topology_config.mobility.eNB_mobility.eNB_mobility_type.selected_option = optarg;
      //oai_emulation.info.omg_model_enb = atoi (optarg);
      break;

    case 'c':
      //strcpy(oai_emulation.info.local_server, optarg);
      strncpy(oai_emulation.info.local_server, optarg, sizeof(oai_emulation.info.local_server));
      oai_emulation.info.local_server[sizeof(oai_emulation.info.local_server) - 1] = 0; // terminate string
      oai_emulation.info.ocg_enabled=1;
      break;

    case 'C':
      oai_emulation.info.tdd_config[0] = atoi (optarg);
      AssertFatal (oai_emulation.info.tdd_config[0] <= TDD_Config__subframeAssignment_sa6, "Illegal tdd_config %d (should be 0-%d)!",
                   oai_emulation.info.tdd_config[0], TDD_Config__subframeAssignment_sa6);
      break;

    case 'D':
      oai_emulation.info.multicast_ifname = strdup(optarg);
      break;

    case 'e':
      oai_emulation.info.extended_prefix_flag[0] = 1;
      break;

    case 'E':
      set_seed = 1;
      oai_emulation.info.seed = atoi (optarg);
      break;

    case 'f':
      forgetting_factor = atof (optarg);
      break;

    case 'F':                   // set FDD
      printf("Setting Frame to FDD\n");
      oai_emulation.info.frame_type[0] = 0;
      oai_emulation.info.frame_type_name[0] = "FDD";
      break;

    case 'g':
      oai_emulation.info.multicast_group = atoi (optarg);
      break;

    case 'G' :
      oai_emulation.info.otg_bg_traffic_enabled = 1;
      break;

    case 'h':
      help ();
      exit (1);
      break;

    case 'H':
      oai_emulation.info.handover_active=1;
      printf("Activate the handover procedure at RRC\n");
      break;

    case 'i':
winckel's avatar
winckel committed
538
#ifdef PROC
539
540
541
      Process_Flag=1;
      node_id = wgt+atoi(optarg);
      port+=atoi(optarg);
winckel's avatar
winckel committed
542
#endif
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
      break;

    case 'I':
      oai_emulation.info.cli_enabled = 1;
      break;

    case 'j' :
      // number of relay nodes: currently only applicable to eMBMS
      oai_emulation.info.nb_rn_local = atoi (optarg);
      break;

    case 'J':
      ue_connection_test=1;
      oai_emulation.info.ocm_enabled=0;
      snr_step = atof(optarg);
      break;

    case 'k':
      //ricean_factor = atof (optarg);
      printf("[SIM] Option k is no longer supported on the command line. Please specify your channel model in the xml template\n");
      exit(-1);
      break;

    case 'K':
      oai_emulation.info.itti_dump_file = optarg;
      break;

    case 'l':
      oai_emulation.info.g_log_level = atoi(optarg);
      break;

    case 'L':                   // set FDD
      flag_LA = atoi(optarg);
      break;

    case 'm':
      target_dl_mcs = atoi (optarg);
      printf("Max target downlink MCS used by MAC scheduler is set to %d\n", target_dl_mcs);
      break;

    case 'M':
      abstraction_flag = 1;
      ethernet_flag = 1;
      oai_emulation.info.ethernet_id = atoi (optarg);
      oai_emulation.info.master_id = oai_emulation.info.ethernet_id;
      oai_emulation.info.ethernet_flag = 1;
      break;

    case 'n':
      oai_emulation.info.n_frames = atoi (optarg);
      oai_emulation.emulation_config.emulation_time_ms= oai_emulation.info.n_frames * 10; // 10 ms frame
      //n_frames = (n_frames >1024) ? 1024: n_frames; // adjust the n_frames if higher that 1024
      oai_emulation.info.n_frames_flag = 1;
      break;

    case 'N':
      Nid_cell = atoi (optarg);

      if (Nid_cell > 503) {
        printf("Illegal Nid_cell %d (should be 0 ... 503)\n", Nid_cell);
winckel's avatar
winckel committed
603
        exit(-1);
604
      }
gauthier's avatar
gauthier committed
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
      break;

    case 'O':
      if (optarg) {
        free(conf_config_file_name); // prevent memory leak if option is used multiple times
        conf_config_file_name = strdup(optarg);
      }

      break;

    case 'o':
      oai_emulation.info.slot_isr = 1;
      break;

    case 'p':
      oai_emulation.info.nb_master = atoi (optarg);
      break;

    case 'P':
      oai_emulation.info.opt_enabled = 1;
      opt_enabled = 1;

      if (strcmp(optarg, "wireshark") == 0) {
        opt_type = OPT_WIRESHARK;
        printf("Enabling OPT for wireshark\n");
      } else if (strcmp(optarg, "pcap") == 0) {
        opt_type = OPT_PCAP;
        printf("Enabling OPT for pcap\n");
      } else {
        printf("Unrecognized option for OPT module. -> Disabling it\n");
        printf("Possible values are either wireshark or pcap\n");
        opt_type = OPT_NONE;
        oai_emulation.info.opt_enabled = 0;
        opt_enabled = 0;
      }

      oai_emulation.info.opt_mode = opt_type;
      break;

    case 'q':
      // openair performane profiler
      oai_emulation.info.opp_enabled = 1; // this var is used for OCG
      opp_enabled = 1; // this is the global var used by oaisim
      break;

    case 'Q':
      //eMBMS_active=1;
      // 0 : not used (default), 1: eMBMS and RRC enabled, 2: eMBMS relaying and RRC enabled, 3: eMBMS enabled, RRC disabled, 4: eMBMS relaying enabled, RRC disabled
      oai_emulation.info.eMBMS_active_state = atoi (optarg);
      break;

    case 'r':
      rate_adaptation_flag = 1;
      break;

    case 'R':
      oai_emulation.info.N_RB_DL[0] = atoi (optarg);

      if ((oai_emulation.info.N_RB_DL[0] != 6) && (oai_emulation.info.N_RB_DL[0] != 15) && (oai_emulation.info.N_RB_DL[0] != 25)
          && (oai_emulation.info.N_RB_DL[0] != 50) && (oai_emulation.info.N_RB_DL[0] != 75) && (oai_emulation.info.N_RB_DL[0] != 100)) {
        printf("Illegal N_RB_DL %d (should be one of 6,15,25,50,75,100)\n", oai_emulation.info.N_RB_DL[0]);
        exit (-1);
      }

      break;

    case 's':
      snr_dB = atoi (optarg);
      //      set_snr = 1;
      oai_emulation.info.ocm_enabled=0;
      break;

    case 'S':
      sinr_dB = atoi (optarg);
      set_sinr = 1;
      oai_emulation.info.ocm_enabled=0;
      break;

    case 't':
      target_ul_mcs = atoi (optarg);
      printf("Max target uplink MCS used by MAC scheduler is set to %d\n", target_ul_mcs);
      break;

    case 'T':
      oai_emulation.info.otg_enabled = 1;
      oai_emulation.info.otg_traffic = optarg;
      break;

    case 'u':
      oai_emulation.info.nb_ue_local = atoi (optarg);
      break;

    case 'U':
      oai_emulation.topology_config.mobility.UE_mobility.UE_mobility_type.selected_option = optarg;
      break;

    case 'v':
      oai_emulation.info.omv_enabled = 1;
      break;

    case 'V':
      ouput_vcd = 1;
      oai_emulation.info.vcd_enabled = 1;
      oai_emulation.info.vcd_file = optarg;
      break;

    case 'w':
      oai_emulation.info.cba_group_active = atoi (optarg);
      break;

    case 'W':
717
#ifdef SMBV
718
719
720
721
722
      config_smbv = 1;

      if(atoi(optarg)!=0)
        strcpy(smbv_ip,optarg);

723
#endif
724
      break;
winckel's avatar
winckel committed
725

726
    case 'x':
727
      /*
728
729
730
      oai_emulation.info.transmission_mode[0] = atoi (optarg);

      if ((oai_emulation.info.transmission_mode[0] != 1) &&  (oai_emulation.info.transmission_mode[0] != 2) && (oai_emulation.info.transmission_mode[0] != 3)
Xiwen JIANG's avatar
Xiwen JIANG committed
731
          && (oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6) && (oai_emulation.info.transmission_mode[0] !=7)) {
732
733
734
        printf("Unsupported transmission mode %d\n",oai_emulation.info.transmission_mode[0]);
        exit(-1);
      }
735
736
737
      */
      printf("Option -x deprecated. Please set transmission mode in eNB config file\n");
      exit(-1);
winckel's avatar
winckel committed
738

739
740
741
      break;

    case 'X':
winckel's avatar
winckel committed
742
#ifdef PROC
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
      temp=atoi(optarg);

      if(temp==0) {
        port=CHANNEL_PORT;
        Channel_Flag=1;
        Process_Flag=0;
        wgt=0;
      } else if(temp==1) {
        port=eNB_PORT;
        wgt=0;
      } else {
        port=UE_PORT;
        wgt=MAX_eNB;
      }

winckel's avatar
winckel committed
758
#endif
759
      break;
winckel's avatar
winckel committed
760

761
    case 'y':
762
      nb_antennas_rx_ue=atoi(optarg);
winckel's avatar
winckel committed
763

764
      if (nb_antennas_rx_ue>4) {
765
766
767
        printf("Cannot have more than 4 antennas\n");
        exit(-1);
      }
winckel's avatar
winckel committed
768

769
      break;
winckel's avatar
winckel committed
770

771
772
773
    case 'Y':
      oai_emulation.info.g_log_verbosity_option = strdup(optarg);
      break;
winckel's avatar
winckel committed
774

775
776
777
778
779
780
781
782
783
784
785
786
787
    case 'z':
      cooperation_flag = atoi (optarg);
      break;

    case 'Z':
      /* Sebastien ROUX: Reserved for future use (currently used in ltenow branch) */
      break;

    default:
      help ();
      exit (-1);
      break;
    }
winckel's avatar
winckel committed
788
  }
789

790
791
792
  if ((oai_emulation.info.nb_enb_local > 0) && (conf_config_file_name != NULL)) {
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
793

794
795
796
    AssertFatal (oai_emulation.info.nb_enb_local <= enb_properties->number,
                 "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!",
                 conf_config_file_name, oai_emulation.info.nb_enb_local, enb_properties->number);
797
798
799

    eth_params = (eth_params_t*)malloc(enb_properties->properties[0]->nb_rrh_gw * sizeof(eth_params_t));
    memset(eth_params, 0, enb_properties->properties[0]->nb_rrh_gw * sizeof(eth_params_t));
knopp's avatar
knopp committed
800
    
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
    for (int j=0; j<enb_properties->properties[0]->nb_rrh_gw; j++) {
      
      if (enb_properties->properties[0]->rrh_gw_config[j].active == 1 ) {
	//	local_remote_radio = BBU_REMOTE_RADIO_HEAD;
	(eth_params+j)->local_if_name             = enb_properties->properties[0]->rrh_gw_config[j].rrh_gw_if_name;
	(eth_params+j)->my_addr                   = enb_properties->properties[0]->rrh_gw_config[j].local_address;
	(eth_params+j)->my_port                   = enb_properties->properties[0]->rrh_gw_config[j].local_port;
	(eth_params+j)->remote_addr               = enb_properties->properties[0]->rrh_gw_config[j].remote_address;
	(eth_params+j)->remote_port               = enb_properties->properties[0]->rrh_gw_config[j].remote_port;
        
	if (enb_properties->properties[0]->rrh_gw_config[j].raw == 1) {
	  (eth_params+j)->transp_preference       = ETH_RAW_MODE; 
	} else if (enb_properties->properties[0]->rrh_gw_config[j].rawif4p5 == 1) {
	  (eth_params+j)->transp_preference       = ETH_RAW_IF4p5_MODE;             
	} else if (enb_properties->properties[0]->rrh_gw_config[j].udpif4p5 == 1) {
	  (eth_params+j)->transp_preference       = ETH_UDP_IF4p5_MODE;             
	} else if (enb_properties->properties[0]->rrh_gw_config[j].rawif5_mobipass == 1) {
	  (eth_params+j)->transp_preference       = ETH_RAW_IF5_MOBIPASS;             
	} else {
	  (eth_params+j)->transp_preference       = ETH_UDP_MODE;	 
	}
      }
    }
824
    /* Update some simulation parameters */
825
826
827
    oai_emulation.info.frame_type[0]           = enb_properties->properties[0]->frame_type[0];
    oai_emulation.info.tdd_config[0]           = enb_properties->properties[0]->tdd_config[0];
    oai_emulation.info.tdd_config_S[0]         = enb_properties->properties[0]->tdd_config_s[0];
828
    oai_emulation.info.extended_prefix_flag[0] = enb_properties->properties[0]->prefix_type[0];
knopp's avatar
knopp committed
829

830
831
832
833
    oai_emulation.info.node_function[0]        = enb_properties->properties[0]->cc_node_function[0];
    oai_emulation.info.node_timing[0]          = enb_properties->properties[0]->cc_node_timing[0];
    downlink_frequency[0][0]                   = enb_properties->properties[0]->downlink_frequency[0];
    uplink_frequency_offset[0][0]              = enb_properties->properties[0]->uplink_frequency_offset[0];
834
    oai_emulation.info.N_RB_DL[0]              = enb_properties->properties[0]->N_RB_DL[0];
835
  }
836

837
838
  free(conf_config_file_name);
  conf_config_file_name = 0;
839
840
}

841
842
void check_and_adjust_params(void)
{
843

gauthier's avatar
gauthier committed
844
  int32_t ret;
845
846
  int i,j;

847
  if (oai_emulation.info.nb_ue_local  + oai_emulation.info.nb_rn_local > NUMBER_OF_UE_MAX) {
848
849
    LOG_E(EMU,"Enter fewer than %d UEs/RNs for the moment or change the NUMBER_OF_UE_MAX\n", NUMBER_OF_UE_MAX);
    exit(EXIT_FAILURE);
850
851
  }

852
  if (oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local > NUMBER_OF_eNB_MAX) {
853
854
    LOG_E(EMU,"Enter fewer than %d eNBs/RNs for the moment or change the NUMBER_OF_UE_MAX\n", NUMBER_OF_eNB_MAX);
    exit(EXIT_FAILURE);
855
  }
856

857
  if (oai_emulation.info.nb_rn_local > NUMBER_OF_RN_MAX) {
858
859
    LOG_E(EMU,"Enter fewer than %d RNs for the moment or change the NUMBER_OF_RN_MAX\n", NUMBER_OF_RN_MAX);
    exit(EXIT_FAILURE);
860
  }
861

862
863
864
865
866
867
868
869
870
871
872
  // fix ethernet and abstraction with RRC_CELLULAR Flag
#ifdef RRC_CELLULAR
  abstraction_flag = 1;
  ethernet_flag = 1;
#endif

  if (set_sinr == 0)
    sinr_dB = snr_dB - 20;

  // setup netdevice interface (netlink socket)
  LOG_I(EMU,"[INIT] Starting NAS netlink interface\n");
Cedric Roux's avatar
Cedric Roux committed
873
  ret = netlink_init();
874

875
  if (ret < 0)
876
    LOG_W(EMU,"[INIT] Netlink not available, careful ...\n");
877
878

  if (ethernet_flag == 1) {
879
880
    oai_emulation.info.master[oai_emulation.info.master_id].nb_ue = oai_emulation.info.nb_ue_local + oai_emulation.info.nb_rn_local;
    oai_emulation.info.master[oai_emulation.info.master_id].nb_enb = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local;
881

882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
    if (oai_emulation.info.nb_rn_local>0)
      LOG_N(EMU,"Ethernet emulation is not yet tested with the relay nodes\n");

    if (!oai_emulation.info.master_id)
      oai_emulation.info.is_primary_master = 1;

    j = 1;

    for (i = 0; i < oai_emulation.info.nb_master; i++) {
      if (i != oai_emulation.info.master_id)
        oai_emulation.info.master_list = oai_emulation.info.master_list + j;

      LOG_I (EMU, "Index of master id i=%d  MASTER_LIST %d\n", i, oai_emulation.info.master_list);
      j *= 2;
    }

    LOG_I (EMU, " Total number of master %d my master id %d\n", oai_emulation.info.nb_master, oai_emulation.info.master_id);
    init_bypass ();

    while (emu_tx_status != SYNCED_TRANSPORT) {
      LOG_I (EMU, " Waiting for EMU Transport to be synced\n");
      emu_transport_sync ();    //emulation_tx_rx();
    }
905
906
  } // ethernet flag

907
  //
908
909
  NB_UE_INST = oai_emulation.info.nb_ue_local + oai_emulation.info.nb_ue_remote;
  NB_eNB_INST = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_enb_remote;
910
911
  NB_RN_INST = oai_emulation.info.nb_rn_local + oai_emulation.info.nb_rn_remote;

912
#if defined(PDCP_USE_NETLINK_QUEUES) && defined(OPENAIR2)
913
914
915
  pdcp_netlink_init();
#endif

916
  if (NB_RN_INST > 0 ) {
917
918
    LOG_N(EMU,"Total number of RN %d (local %d, remote %d) mobility (the same as eNB) %s  \n", NB_RN_INST,oai_emulation.info.nb_rn_local,oai_emulation.info.nb_rn_remote,
          oai_emulation.topology_config.mobility.eNB_mobility.eNB_mobility_type.selected_option);
919

920
    LOG_N(EMU,"Adjust the number of eNB inst (%d->%d) and UE inst (%d->%d)\n ",
gauthier's avatar
gauthier committed
921
922
          NB_eNB_INST, NB_eNB_INST+NB_RN_INST,
          NB_UE_INST, NB_UE_INST+NB_RN_INST);
923
924
    NB_eNB_INST+=NB_RN_INST;
    NB_UE_INST+=NB_RN_INST;
925
  }
926

927
  LOG_I(EMU,"Total number of UE %d (first local %d , num local %d, remote %d, relay %d) mobility %s \n",
928
929
930
        NB_UE_INST,oai_emulation.info.first_ue_local, oai_emulation.info.nb_ue_local,oai_emulation.info.nb_ue_remote,
        NB_RN_INST,
        oai_emulation.topology_config.mobility.UE_mobility.UE_mobility_type.selected_option);
931
932

  LOG_I(EMU,"Total number of eNB %d (local %d, remote %d, relay %d) mobility %s \n",
933
934
935
        NB_eNB_INST,oai_emulation.info.nb_enb_local,oai_emulation.info.nb_enb_remote,
        NB_RN_INST,
        oai_emulation.topology_config.mobility.eNB_mobility.eNB_mobility_type.selected_option);
936

937
938
}

939
#ifdef OPENAIR2
940
941
void init_omv(void)
{
942
943
  if (oai_emulation.info.omv_enabled == 1) {

944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
    if(pipe(pfd) == -1)
      perror("pipe error \n");

    snprintf( full_name, sizeof(full_name), "%s/UTIL/OMV/OMV",getenv("OPENAIR2_DIR") );
    LOG_I(EMU,"Stating the OMV path %s pfd[0] %d pfd[1] %d \n", full_name, pfd[0],pfd[1]);

    switch(fork()) {
    case -1 :
      perror("fork failed \n");
      break;

    case 0 : // child is going to be the omv, it is the reader
      if(close(pfd[1]) == -1 ) // we close the write desc.
        perror("close on write\n" );

      sprintf(fdstr, "%d", pfd[0] );
      sprintf(num_enb, "%d", NB_eNB_INST);
      sprintf(num_ue, "%d", NB_UE_INST);
      sprintf(x_area, "%f", oai_emulation.topology_config.area.x_m );
      sprintf(y_area, "%f", oai_emulation.topology_config.area.y_m );
      sprintf(z_area, "%f", 200.0 );
      sprintf(frames, "%d", oai_emulation.info.n_frames);
      sprintf(nb_antenna, "%d", 4);
      sprintf(frame_type, "%s", (oai_emulation.info.frame_type[0] == 0) ? "FDD" : "TDD");
      sprintf(tdd_config, "%d", oai_emulation.info.tdd_config[0]);
      // execl is used to launch the visualisor
      execl(full_name,"OMV", fdstr, frames, num_enb, num_ue, x_area, y_area, z_area, nb_antenna, frame_type, tdd_config,NULL );
      perror( "error in execl the OMV" );
    }

    //parent
    if(close( pfd[0] ) == -1 ) // we close the write desc.
      perror("close on read\n" );
977
978
  }
}
979
#endif
980

981
982
void init_seed(uint8_t set_seed)
{
983
984
985

  if(set_seed) {

986
987
    randominit (oai_emulation.info.seed);
    set_taus_seed (oai_emulation.info.seed);
988
989

  } else {
990
991
    randominit (0);
    set_taus_seed (0);
992
993
994
  }
}

995
996
997
998
999
openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];

1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
int eNB_trx_start(openair0_device *device) {
  return(0);
}

void eNB_trx_end(openair0_device *device) {
  return;
}

int eNB_trx_stop(openair0_device *device) {
  return(0);
}
int UE_trx_start(openair0_device *device) {
  return(0);
}
int UE_trx_end(openair0_device *device) {
  return(0);
}
int UE_trx_stop(openair0_device *device) {
  return(0);
}
int eNB_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
  return(0);
}
int eNB_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
  return(0);
}
int UE_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
  return(0);
}
int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
  return(0);
}

1033
1034
extern pthread_mutex_t subframe_mutex;
extern int subframe_eNB_mask,subframe_UE_mask;
1035

1036
int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
1037
1038
1039
1040

  int eNB_id = device->Mod_id;
  int CC_id  = device->CC_id;

1041
1042
1043
1044
1045
  int subframe;
  int sample_count=0;

  *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id];

1046
  LOG_D(EMU,"eNB_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
1047
1048
1049
1050
1051
1052
1053
1054
        (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id],
        (unsigned long long)last_eNB_rx_timestamp[eNB_id][CC_id],
	(*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10);
  // if we're at a subframe boundary generate UL signals for this eNB

  while (sample_count<nsamps) {
    while (current_eNB_rx_timestamp[eNB_id][CC_id]<
	   (nsamps+last_eNB_rx_timestamp[eNB_id][CC_id])) {
1055
      //      LOG_D(EMU,"eNB: current TS %llu, last TS %llu, sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]);
1056
1057
1058
1059
1060
1061
1062
1063
1064
      usleep(500);
    }

    // tell top-level we are busy
    pthread_mutex_lock(&subframe_mutex);
    subframe_eNB_mask|=(1<<eNB_id);
    pthread_mutex_unlock(&subframe_mutex); 
    
    subframe = (last_eNB_rx_timestamp[eNB_id][CC_id]/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
1065
    LOG_D(EMU,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
1066
1067
1068
1069
	  subframe,(unsigned long long)*ptimestamp,
	  (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]);
    
    do_UL_sig(UE2eNB,
1070
1071
1072
	      enb_data,
	      ue_data,
	      subframe,
1073
	      0,  // abstraction_flag
1074
	      &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
1075
1076
	      0,  // frame is only used for abstraction
	      eNB_id,
1077
	      CC_id);
1078
1079
1080
  
    last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
    sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
1081
  }
knopp's avatar
knopp committed
1082
1083
  

1084
1085

  return(nsamps);
1086
1087
}

1088
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
1089
1090
1091

  int UE_id = device->Mod_id;
  int CC_id  = device->CC_id;
1092
1093
1094
1095
1096
1097
  int subframe;
  int sample_count=0;
  int read_size;

  *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];

knopp's avatar
knopp committed
1098
  LOG_D(EMU,"UE_trx_read nsamps %d TS(%llu,%llu) antenna %d\n",nsamps,
1099
        (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
knopp's avatar
knopp committed
1100
1101
        (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
	cc);
1102
1103
1104
1105
1106
1107
1108
1109
1110

  if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)
    read_size = nsamps;
  else
    read_size = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;

  while (sample_count<nsamps) {
    while (current_UE_rx_timestamp[UE_id][CC_id] < 
	   (last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
1111
      //LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
knopp's avatar
knopp committed
1112

1113
1114
      usleep(500);
    }
1115

1116
    //    LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
1117
1118
1119
1120
1121
      
    // tell top-level we are busy 
    pthread_mutex_lock(&subframe_mutex);
    subframe_UE_mask|=(1<<UE_id);
    pthread_mutex_unlock(&subframe_mutex);
knopp's avatar
knopp committed
1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138

    // otherwise we have one subframe here so generate the received signal
    subframe = (last_UE_rx_timestamp[UE_id][CC_id]/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
    if ((last_UE_rx_timestamp[UE_id][CC_id]%PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) > 0)
      subframe++;

    last_UE_rx_timestamp[UE_id][CC_id] += read_size;
    sample_count += read_size;
 
    if (subframe > 9) 
      return(nsamps);

    LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n",
	  subframe,(unsigned long long)*ptimestamp,
	  (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]);    
    do_DL_sig(eNB2UE,
1139
1140
1141
	      enb_data,
	      ue_data,
	      subframe,
1142
1143
1144
	      0, //abstraction_flag,
	      &PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
	      UE_id,
1145
	      CC_id);
knopp's avatar
knopp committed
1146
1147


1148
  }
knopp's avatar
knopp committed
1149
1150


1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  return(nsamps);
}

int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {

  return(nsamps);
}

int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {

  return(nsamps);
1162
1163
}

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
void init_openair0(void);

openair0_config_t openair0_cfg[MAX_CARDS];

void init_openair0() {

  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {

    openair0_cfg[card].configFilename = NULL;

    if(frame_parms[0]->N_RB_DL == 100) {
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
	openair0_cfg[card].samples_per_frame = 230400; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
      else {
	openair0_cfg[card].sample_rate=30.72e6;
	openair0_cfg[card].samples_per_frame = 307200; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }

    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    
    openair0_cfg[card].remote_addr    = (eth_params+card)->remote_addr;
    openair0_cfg[card].remote_port    = (eth_params+card)->remote_port;
    openair0_cfg[card].my_addr        = (eth_params+card)->my_addr;
    openair0_cfg[card].my_port        = (eth_params+card)->my_port;    
     
    
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
           PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx,
           PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx);
    openair0_cfg[card].Mod_id = 0;



    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
    openair0_cfg[card].tx_num_channels=min(2,PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx);
    openair0_cfg[card].rx_num_channels=min(2,PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx);

    for (i=0; i<4; i++) {

      openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_dB;
      
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
    }
  }
}

1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
void init_devices(void){

  module_id_t UE_id, eNB_id;
  uint8_t CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (eNB_id=0;eNB_id<NB_eNB_INST;eNB_id++) {
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.Mod_id             = eNB_id;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.CC_id              = CC_id;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_start_func     = eNB_trx_start;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_read_func      = eNB_trx_read;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_write_func     = eNB_trx_write;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_end_func       = eNB_trx_end;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_stop_func      = eNB_trx_stop;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_freq_func  = eNB_trx_set_freq;
      PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_gains_func = eNB_trx_set_gains;
1259
1260
      current_eNB_rx_timestamp[eNB_id][CC_id] = PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
      last_eNB_rx_timestamp[eNB_id][CC_id] = 0;
1261
    }
1262
    for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
1263
1264
1265
1266
1267
1268
1269
1270
1271
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.Mod_id               = UE_id;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.CC_id                = CC_id;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_start_func       = UE_trx_start;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_read_func        = UE_trx_read;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_write_func       = UE_trx_write;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_end_func         = UE_trx_end;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_stop_func        = UE_trx_stop;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_freq_func    = UE_trx_set_freq;
      PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_gains_func   = UE_trx_set_gains;
1272
1273
1274
      current_UE_rx_timestamp[UE_id][CC_id] = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
      last_UE_rx_timestamp[UE_id][CC_id] = 0;

1275
1276
1277
1278
    }
  }
}

1279
1280
void init_openair1(void)
{
gauthier's avatar
gauthier committed
1281
  module_id_t UE_id, eNB_id;
knopp's avatar
   
knopp committed
1282
  uint8_t CC_id;
1283
#if ENABLE_RAL
1284
1285
  int list_index;
#endif
1286

1287
  // change the nb_connected_eNB
1288
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1289
1290
1291
1292
1293
1294
    init_lte_vars (&frame_parms[CC_id], 
		   oai_emulation.info.frame_type[CC_id], 
		   oai_emulation.info.tdd_config[CC_id], 
		   oai_emulation.info.tdd_config_S[CC_id],
		   oai_emulation.info.extended_prefix_flag[CC_id],
                   oai_emulation.info.N_RB_DL[CC_id], 
1295
		   enb_properties->properties[0]->Nid_cell[CC_id], 
1296
1297
1298
		   cooperation_flag, 
		   enb_properties->properties[0]->nb_antenna_ports[CC_id], 
		   abstraction_flag,
1299
		   enb_properties->properties[0]->nb_antennas_rx[CC_id],
1300
1301
		   enb_properties->properties[0]->nb_antennas_tx[CC_id],
		   nb_antennas_rx_ue,
1302
		   oai_emulation.info.eMBMS_active_state);
1303
1304
1305
1306
1307

    // This is for IF4p5 RRU, gets done by RRC configuration of eNB
    PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[0]->prach_config_index[CC_id];
    PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset  = enb_properties->properties[0]->prach_freq_offset[CC_id];

knopp's avatar
   
knopp committed
1308
  }
1309

1310
1311
1312
1313
1314
1315
  for (eNB_id=0; eNB_id<NB_eNB_INST; eNB_id++) {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK;
        PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_RI_Index  = beta_RI;
        PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = beta_CQI;
1316
        PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antenna_ports_eNB>1) ? 1 : 0; // rho_A = rho_B
1317
1318
1319
1320

        PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = beta_ACK;
        PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_RI_Index  = beta_RI;
        PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = beta_CQI;
1321
        PHY_vars_UE_g[UE_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antenna_ports_eNB>1) ? 1 : 0; // rho_A = rho_B
1322
      }
1323
    }
1324
1325
  }

1326
1327
  printf ("AFTER init: MAX_NUM_CCs %d, Nid_cell %d frame_type %d,tdd_config %d\n",
          MAX_NUM_CCs,