oaisim_functions.c 67.2 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
/*! \file oaisim_functions.c
* \brief function primitives of oaisim
24
* \author Navid Nikaein
25
26
27
28
29
30
31
* \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

Cedric Roux's avatar
Cedric Roux committed
94
#ifndef min
95
#define min(a,b) ((a)<(b)?(a):(b))
Cedric Roux's avatar
Cedric Roux committed
96
#endif
97

gauthier's avatar
gauthier committed
98
99
100
101
int           otg_times             = 0;
int           if_times              = 0;
int           for_times             = 0;

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

Florian Kaltenberger's avatar
Florian Kaltenberger committed
138
139
int phy_test = 0;

140
141
142
143
#ifdef OPENAIR2
// omv related info
//pid_t omv_pid;
char full_name[200];
144
extern int pfd[2]; // fd for omv : fixme: this could be a local var
145
146
147
148
149
150
151
152
153
154
155
156
157
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
158
Packet_OTG_List_t *otg_pdcp_buffer = NULL;
159
160
161

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
162
163
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];
164
165

extern mapping small_scale_names[];
Cedric Roux's avatar
Cedric Roux committed
166
#if defined(Rel10) || defined(Rel14)
gauthier's avatar
gauthier committed
167
168
169
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
170

171
172
extern time_stats_t dl_chan_stats;
extern time_stats_t ul_chan_stats;
173

174
175
extern int xforms;

176

177
178
179
extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];

180
181
182
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);
183
184
void stop_eNB(int nb_inst);

185
186
const Enb_properties_array_t *enb_properties;

187
int oaisim_flag=1;
188

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

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

gauthier's avatar
gauthier committed
197
    LONG_OPTION_ENB_CONF,
winckel's avatar
winckel committed
198

gauthier's avatar
gauthier committed
199
200
    LONG_OPTION_PDNC_PERIOD,
    LONG_OPTION_OMG_PERIOD,
201
    LONG_OPTION_OEH_ENABLED,
winckel's avatar
winckel committed
202

gauthier's avatar
gauthier committed
203
204
205
206
    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
207

gauthier's avatar
gauthier committed
208
209
210
    LONG_OPTION_ENB_MIHF_REMOTE_PORT,
    LONG_OPTION_ENB_MIHF_IP_ADDRESS,
    LONG_OPTION_ENB_MIHF_ID,
winckel's avatar
winckel committed
211

gauthier's avatar
gauthier committed
212
213
214
215
    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
216

gauthier's avatar
gauthier committed
217
218
219
    LONG_OPTION_UE_MIHF_REMOTE_PORT,
    LONG_OPTION_UE_MIHF_IP_ADDRESS,
    LONG_OPTION_UE_MIHF_ID,
gauthier's avatar
gauthier committed
220
221

    LONG_OPTION_MALLOC_TRACE_ENABLED,
222
223

    LONG_OPTION_CBA_BACKOFF_TIMER,
224

Florian Kaltenberger's avatar
Florian Kaltenberger committed
225
    LONG_OPTION_PHYTEST,
226
    LONG_OPTION_XFORMS,
Cedric Roux's avatar
Cedric Roux committed
227
228
229
230

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

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

238
239
240
    {"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
241

242
243
244
245
    {"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
246

247
248
249
    {"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
250

251
252
253
254
    {"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
255

256
257
258
    {"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},
259

260
    {"malloc-trace-enabled",   no_argument,       0, LONG_OPTION_MALLOC_TRACE_ENABLED},
261

262
    {"cba-backoff",            required_argument, 0, LONG_OPTION_CBA_BACKOFF_TIMER},
263

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

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

273
    {NULL, 0, NULL, 0}
winckel's avatar
winckel committed
274
  };
winckel's avatar
winckel committed
275

276
  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) {
277
    switch (option) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
278
279
280
281
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;

282
283
284
285
286
287
    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
288

289
      break;
winckel's avatar
winckel committed
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
318
319
    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
320

321
#if ENABLE_RAL
winckel's avatar
winckel committed
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
432
433
    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;
434
#endif
435

436
437
438
439
    case LONG_OPTION_XFORMS:
      xforms=1;
      break;

Cedric Roux's avatar
Cedric Roux committed
440
441
442
443
444
445
446
447
448
449
450
451
452
#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;
    }
453
454
455
456
457
458

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

461
462
    case 'a':
      abstraction_flag = 1;
463
464
      printf("FATAL: -a flag not functional for the moment.\nWe are working on fixing the abstraction mode.\n");
      exit(1);
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
538
539
540
541
      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
542
#ifdef PROC
543
544
545
      Process_Flag=1;
      node_id = wgt+atoi(optarg);
      port+=atoi(optarg);
winckel's avatar
winckel committed
546
#endif
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
603
604
605
606
      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
607
        exit(-1);
608
      }
gauthier's avatar
gauthier committed
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
717
718
719
720
      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':
721
#ifdef SMBV
722
723
724
725
726
      config_smbv = 1;

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

727
#endif
728
      break;
winckel's avatar
winckel committed
729

730
    case 'x':
731
      /*
732
733
      oai_emulation.info.transmission_mode[0] = atoi (optarg);

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

744
745
746
      break;

    case 'X':
winckel's avatar
winckel committed
747
#ifdef PROC
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
      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
763
#endif
764
      break;
winckel's avatar
winckel committed
765

766
    case 'y':
767
      nb_antennas_rx_ue=atoi(optarg);
winckel's avatar
winckel committed
768

769
      if (nb_antennas_rx_ue>4) {
770
771
772
        printf("Cannot have more than 4 antennas\n");
        exit(-1);
      }
winckel's avatar
winckel committed
773

774
      break;
winckel's avatar
winckel committed
775

776
777
778
    case 'Y':
      oai_emulation.info.g_log_verbosity_option = strdup(optarg);
      break;
winckel's avatar
winckel committed
779

780
781
782
783
784
785
786
787
788
789
790
791
792
    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
793
  }
794

795
796
797
  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);
798

799
800
801
    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);
802
803
804

    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
805
    
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
    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;	 
	}
      }
    }
829
    /* Update some simulation parameters */
830
831
832
    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];
833
    oai_emulation.info.extended_prefix_flag[0] = enb_properties->properties[0]->prefix_type[0];
knopp's avatar
knopp committed
834

835
836
837
838
    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];
839
    oai_emulation.info.N_RB_DL[0]              = enb_properties->properties[0]->N_RB_DL[0];
840
  }
841

842
843
  free(conf_config_file_name);
  conf_config_file_name = 0;
844
845
}

846
847
void check_and_adjust_params(void)
{
848

gauthier's avatar
gauthier committed
849
  int32_t ret;
850
851
  int i,j;

852
  if (oai_emulation.info.nb_ue_local  + oai_emulation.info.nb_rn_local > NUMBER_OF_UE_MAX) {
853
854
    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);
855
856
  }

857
  if (oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local > NUMBER_OF_eNB_MAX) {
858
859
    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);
860
  }
861

862
  if (oai_emulation.info.nb_rn_local > NUMBER_OF_RN_MAX) {
863
864
    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);
865
  }
866

867
868
869
870
871
872
873
874
875
876
877
  // 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
878
  ret = netlink_init();
879

880
  if (ret < 0)
881
    LOG_W(EMU,"[INIT] Netlink not available, careful ...\n");
882
883

  if (ethernet_flag == 1) {
884
885
    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;
886

887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
    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();
    }
910
911
  } // ethernet flag

912
  //
913
914
  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;
915
916
  NB_RN_INST = oai_emulation.info.nb_rn_local + oai_emulation.info.nb_rn_remote;

917
#if defined(PDCP_USE_NETLINK_QUEUES) && defined(OPENAIR2)
918
919
920
  pdcp_netlink_init();
#endif

921
  if (NB_RN_INST > 0 ) {
922
923
    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);
924

925
    LOG_N(EMU,"Adjust the number of eNB inst (%d->%d) and UE inst (%d->%d)\n ",
gauthier's avatar
gauthier committed
926
927
          NB_eNB_INST, NB_eNB_INST+NB_RN_INST,
          NB_UE_INST, NB_UE_INST+NB_RN_INST);
928
929
    NB_eNB_INST+=NB_RN_INST;
    NB_UE_INST+=NB_RN_INST;
930
  }
931

932
  LOG_I(EMU,"Total number of UE %d (first local %d , num local %d, remote %d, relay %d) mobility %s \n",
933
934
935
        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);
936
937

  LOG_I(EMU,"Total number of eNB %d (local %d, remote %d, relay %d) mobility %s \n",
938
939
940
        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);
941

942
943
}

944
#ifdef OPENAIR2
945
946
void init_omv(void)
{
947
948
  if (oai_emulation.info.omv_enabled == 1) {

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
977
978
979
980
981
    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" );
982
983
  }
}
984
#endif
985

986
987
void init_seed(uint8_t set_seed)
{
988
989
990

  if(set_seed) {

991
992
    randominit (oai_emulation.info.seed);
    set_taus_seed (oai_emulation.info.seed);
993
994

  } else {
995
996
    randominit (0);
    set_taus_seed (0);
997
998
999
  }
}

1000
1001
1002
1003
1004
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];

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
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);
}
Cedric Roux's avatar
Cedric Roux committed
1019
1020
void UE_trx_end(openair0_device *device) {
  return;
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
}
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);
}

1038
1039
extern pthread_mutex_t subframe_mutex;
extern int subframe_eNB_mask,subframe_UE_mask;
1040

1041
1042
1043
int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
  int ret = nsamps;
1044
1045
1046
  int eNB_id = device->Mod_id;
  int CC_id  = device->CC_id;

1047
  int subframe;
1048
1049
  int read_samples, max_samples;
  openair0_timestamp last = last_eNB_rx_timestamp[eNB_id][CC_id];
1050
1051
1052

  *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id];

1053
1054
1055
1056
  LOG_D(EMU,"eNB_trx_read nsamps %d TS(%"PRId64",%"PRId64") => subframe %d\n",nsamps,
        current_eNB_rx_timestamp[eNB_id][CC_id],
        last_eNB_rx_timestamp[eNB_id][CC_id],
	(int)((*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10));
1057
1058
  // if we're at a subframe boundary generate UL signals for this eNB

1059
1060
  while (nsamps) {
    while (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
1061
      LOG_D(EMU,"eNB: current TS %"PRId64", last TS %"PRId64", sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]);
1062
1063
1064
      usleep(500);
    }

1065
1066
1067
1068
    read_samples = nsamps;
    max_samples = current_eNB_rx_timestamp[eNB_id][CC_id]-last;
    if (read_samples > max_samples)
      read_samples = max_samples;
1069

1070
1071
    last += read_samples;
    nsamps -= read_samples;
knopp's avatar
knopp committed
1072

1073
1074
1075
    if (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
      subframe = (last/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
      //subframe = (subframe+9) % 10;
1076

1077
1078
1079
      LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
            subframe,(unsigned long long)*ptimestamp,
            (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]);
1080
    
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
      do_UL_sig(UE2eNB,
                enb_data,
                ue_data,
                subframe,
                0,  // abstraction_flag
                &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
                0,  // frame is only used for abstraction
                eNB_id,
                CC_id);

      last_eNB_rx_timestamp[eNB_id][CC_id] = last;
    }
1093
  }
knopp's avatar
knopp committed
1094
  
1095
  last_eNB_rx_timestamp[eNB_id][CC_id] = last;
1096

1097
  return ret;
1098
1099
}

1100
1101
1102
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
  int ret = nsamps;
1103
1104
  int UE_id = device->Mod_id;
  int CC_id  = device->CC_id;
1105
  int subframe;
1106
1107
  int read_samples, max_samples;
  openair0_timestamp last = last_UE_rx_timestamp[UE_id][CC_id];
1108
1109
1110

  *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];

knopp's avatar
knopp committed
1111
  LOG_D(EMU,"UE_trx_read nsamps %d TS(%llu,%llu) antenna %d\n",nsamps,
1112
        (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
knopp's avatar
knopp committed
1113
1114
        (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
	cc);
1115

1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
  while (nsamps) {
    /* wait for all processing to be finished */
    while (1) {
      PHY_VARS_UE *UE = PHY_vars_UE_g[UE_id][0];
      int ready = 1;
      int i;
      for (i = 0; i < 2; i++)
        if (UE->proc.proc_rxtx[i].instance_cnt_rxtx >= 0) ready = 0;
      if (UE->proc.instance_cnt_synch >= 0) ready = 0;
      if (ready) break;
      usleep(500);
    }
    while (current_UE_rx_timestamp[UE_id][CC_id] == last) {
1129
      LOG_D(EMU,"UE_trx_read : current TS %"PRId64", last TS %"PRId64", sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
knopp's avatar
knopp committed
1130

1131
1132
      usleep(500);
    }
1133

1134
    //    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]);
1135
      
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
    read_samples = nsamps;
    max_samples = current_UE_rx_timestamp[UE_id][CC_id]-last;
    if (read_samples > max_samples)
      read_samples = max_samples;

    last += read_samples;
    nsamps -= read_samples;

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

      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,
                enb_data,
                ue_data,
                subframe,
                0, //abstraction_flag,
                &PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
                UE_id,
                CC_id);

      last_UE_rx_timestamp[UE_id][CC_id] = last;
    }
1164
  }
knopp's avatar
knopp committed
1165

1166
  last_UE_rx_timestamp[UE_id][CC_id] = last;
knopp's avatar
knopp committed
1167

1168
  return ret;
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
}

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);
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
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
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]);
    }
  }
}

1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
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;
1276
1277
      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;
1278
    }
1279
    for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
1280
1281
1282
1283
1284
1285
1286
1287
1288
      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;
1289
1290
1291
      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;

1292
1293
1294
1295
    }
  }
}

1296
1297
void init_openair1(void)
{
Cedric Roux's avatar
Cedric Roux committed
1298
  module_id_t UE_id, eNB_id = 0;
knopp's avatar
   
knopp committed
1299
  uint8_t CC_id;
1300
#if ENABLE_RAL
1301
1302
  int list_index;
#endif
1303

1304
  // change the nb_connected_eNB
1305
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1306
1307
1308
    init_lte_vars (&frame_parms[CC_id],
		   oai_emulation.info.frame_type[CC_id],
		   oai_emulation.info.tdd_config[CC_id],
1309
1310
1311
		   oai_emulation.info.tdd_config_S[CC_id],
		   oai_emulation.info.extended_prefix_flag[CC_id],
                   oai_emulation.info.N_RB_DL[CC_id], 
knopp's avatar