Files
openairinterface5g/targets/SIMU/USER/oaisim_functions.c
T
Bi-Ruei, Chiu 5c23af773a Compare version number using MAKE_VERSION macro to provide better SW configuration:
1. Previous SW configuration for different RRC version relies on whether macro Rel10,
   Rel14 defined or not by checking #ifdef Rel14 or #if defined(Rel10) || defined(R14).
   Whenever there is a newer RRC version, e.g. Rel15, it will be very a tedious and
   error-prone job to add defined(Rel15) in every place.

2. Some RRC messages are defined in release 13 instead of release 14, NB-IoT
   feature is one of such example. Our code shall reflect this fact instead of using
   an afterward version number in software configuration.

3. Some RRC messages or some fields of certain RRC messages are added in the middle
   a release, e.g. SystemInformationBlockType1_v1310_IEs_t defined in RRC 13.1.0
   and RRC 9.2.0 made some changes to SIB12 and SIB13 so we have sib12_v920 and
   sib13_v920 fields in SIB12 and SIB13's struct.
   We need a finer grain of control when using ASN1 from different RRC version.

4. S1AP also has this problem that it use UPDATE_RELEASE_9 and UPDATE_RELEASE_10 to
   differentiate between various S1AP version.

This commit propose using MAKE_VERSION(x,y,z) to designate the version number and
modify current conditional compilation accordingly.

Note: 2018/04/16, Modified based on Cedric's comment.
2018-04-16 12:32:29 +02:00

1826 lines
60 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \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
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>
#include <time.h>
#include <mcheck.h>
#include <sys/timerfd.h>
#include "assertions.h"
#include "oaisim_functions.h"
#include "PHY/extern.h"
#include "LAYER2/MAC/extern.h"
#ifdef OPENAIR2
#include "LAYER2/MAC/proto.h"
#endif
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
#include "LAYER2/PDCP_v10.1.0/pdcp_primitives.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "PHY_INTERFACE/extern.h"
//#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "SCHED/extern.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "UTIL/OTG/otg_config.h"
#include "UTIL/OTG/otg_tx.h"
#if ENABLE_RAL
#include "lteRALenb.h"
#include "lteRALue.h"
#endif
#include "cor_SF_sim.h"
#include "enb_config.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#if defined(ENABLE_USE_MME)
# include "s1ap_eNB.h"
#endif
#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
#include "ENB_APP/enb_paramdef.h"
#include "common/config/config_userapi.h"
#ifdef SMBV
extern uint8_t config_smbv;
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
int otg_times = 0;
int if_times = 0;
int for_times = 0;
uint16_t Nid_cell = 0; //needed by init_lte_vars
int nb_antennas_rx_ue = 1; // //
uint8_t target_dl_mcs = 16; // max mcs used by MAC scheduler
uint8_t rate_adaptation_flag = 0;
uint8_t set_snr = 0;
uint8_t set_sinr = 0;
double snr_dB=0, sinr_dB=0;
uint8_t set_seed = 0;
uint8_t cooperation_flag; // for cooperative communication
uint8_t abstraction_flag = 0;
uint8_t ethernet_flag = 0;
double snr_step = 1.0;
uint8_t ue_connection_test = 0;
double forgetting_factor = 0.0;
uint8_t beta_ACK = 0;
uint8_t beta_RI = 0;
uint8_t beta_CQI = 2;
uint8_t target_ul_mcs = 16;
//LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
int map1,map2;
double **ShaF = NULL;
// pointers signal buffers (s = transmit, r,r0 = receive)
double **s_re, **s_im, **r_re, **r_im, **r_re0, **r_im0;
node_list* ue_node_list = NULL;
node_list* enb_node_list = NULL;
int omg_period = 10000;
int pdcp_period = 0;
int cba_backoff = 30;
// time calibration for soft realtime mode
struct timespec time_spec;
unsigned long time_last = 0;
unsigned long time_now = 0;
int td = 0;
int td_avg = 0;
int sleep_time_us = 0;
int phy_test = 0;
#ifdef OPENAIR2
// omv related info
//pid_t omv_pid;
char full_name[200];
extern int pfd[2]; // fd for omv : fixme: this could be a local var
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
Packet_OTG_List_t *otg_pdcp_buffer = NULL;
extern node_desc_t *enb_data[NUMBER_OF_RU_MAX];
extern node_desc_t *ue_data[NUMBER_OF_UE_MAX];
extern channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
extern channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs];
extern mapping small_scale_names[];
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
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
extern time_stats_t dl_chan_stats;
extern time_stats_t ul_chan_stats;
extern int xforms;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
int oaisim_flag=1;
void RCConfig_sim(void) {
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
// Get num RU instances
config_getlist( &RUParamList,NULL,0, NULL);
RC.nb_RU = RUParamList.numelt;
}
void get_simulation_options(int argc, char *argv[])
{
int option;
enum long_option_e {
LONG_OPTION_START = 0x100, /* Start after regular single char options */
LONG_OPTION_ENB_CONF,
LONG_OPTION_PDNC_PERIOD,
LONG_OPTION_OMG_PERIOD,
LONG_OPTION_OEH_ENABLED,
LONG_OPTION_ENB_RAL_LISTENING_PORT,
LONG_OPTION_ENB_RAL_IP_ADDRESS,
LONG_OPTION_ENB_RAL_LINK_ID,
LONG_OPTION_ENB_RAL_LINK_ADDRESS,
LONG_OPTION_ENB_MIHF_REMOTE_PORT,
LONG_OPTION_ENB_MIHF_IP_ADDRESS,
LONG_OPTION_ENB_MIHF_ID,
LONG_OPTION_UE_RAL_LISTENING_PORT,
LONG_OPTION_UE_RAL_IP_ADDRESS,
LONG_OPTION_UE_RAL_LINK_ID,
LONG_OPTION_UE_RAL_LINK_ADDRESS,
LONG_OPTION_UE_MIHF_REMOTE_PORT,
LONG_OPTION_UE_MIHF_IP_ADDRESS,
LONG_OPTION_UE_MIHF_ID,
LONG_OPTION_MALLOC_TRACE_ENABLED,
LONG_OPTION_CBA_BACKOFF_TIMER,
LONG_OPTION_PHYTEST,
LONG_OPTION_XFORMS,
#if T_TRACER
LONG_OPTION_T_PORT,
LONG_OPTION_T_NOWAIT,
LONG_OPTION_T_DONT_FORK,
#endif
};
static struct option long_options[] = {
{"enb-conf", required_argument, 0, LONG_OPTION_ENB_CONF},
{"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},
{"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},
{"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},
{"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},
{"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},
{"malloc-trace-enabled", no_argument, 0, LONG_OPTION_MALLOC_TRACE_ENABLED},
{"cba-backoff", required_argument, 0, LONG_OPTION_CBA_BACKOFF_TIMER},
{"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
{"xforms", no_argument, 0, LONG_OPTION_XFORMS},
#if T_TRACER
{"T_port", required_argument, 0, LONG_OPTION_T_PORT},
{"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT},
{"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK},
#endif
{NULL, 0, NULL, 0}
};
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) {
switch (option) {
case LONG_OPTION_PHYTEST:
phy_test = 1;
break;
case LONG_OPTION_ENB_CONF:
if (optarg) {
free(RC.config_file_name); // prevent memory leak if option is used multiple times
RC.config_file_name = strdup(optarg);
printf("eNB configuration file is %s\n", RC.config_file_name);
}
break;
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;
#if ENABLE_RAL
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;
#endif
case LONG_OPTION_XFORMS:
xforms=1;
break;
#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;
}
case LONG_OPTION_T_DONT_FORK: {
extern int T_dont_fork;
T_dont_fork = 1;
break;
}
#endif
case 'a':
abstraction_flag = 1;
printf("FATAL: -a flag not functional for the moment.\nWe are working on fixing the abstraction mode.\n");
exit(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':
#ifdef PROC
Process_Flag=1;
node_id = wgt+atoi(optarg);
port+=atoi(optarg);
#endif
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);
exit(-1);
}
break;
case 'O':
if (optarg) {
free(RC.config_file_name); // prevent memory leak if option is used multiple times
RC.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':
#ifdef SMBV
config_smbv = 1;
if(atoi(optarg)!=0)
strcpy(smbv_ip,optarg);
#endif
break;
case 'x':
/*
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) && (oai_emulation.info.transmission_mode[0] != 4) &&
(oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6)) && (oai_emulation.info.transmission_mode[0] !=7)) {
printf("Unsupported transmission mode %d\n",oai_emulation.info.transmission_mode[0]);
exit(-1);
}
*/
printf("Option -x deprecated. Please set transmission mode in eNB config file\n");
exit(-1);
break;
case 'X':
#ifdef PROC
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;
}
#endif
break;
case 'y':
nb_antennas_rx_ue=atoi(optarg);
if (nb_antennas_rx_ue>4) {
printf("Cannot have more than 4 antennas\n");
exit(-1);
}
break;
case 'Y':
oai_emulation.info.g_log_verbosity_option = strdup(optarg);
break;
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;
}
}
if ( load_configmodule(argc,argv) == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
if (RC.config_file_name != NULL) {
/* Read eNB configuration file */
RCConfig_sim();
printf("returned with %d eNBs, %d rus\n",RC.nb_inst,RC.nb_RU);
oai_emulation.info.nb_enb_local = RC.nb_inst;
oai_emulation.info.nb_ru_local = RC.nb_RU;
/*
for (int j=0; j<enb_properties->nb_ru; j++) {
// local_remote_radio = BBU_REMOTE_RADIO_HEAD;
(eth_params+j)->local_if_name = enb_properties->ru_config[j]->ru_if_name;
(eth_params+j)->my_addr = enb_properties->ru_config[j]->local_address;
(eth_params+j)->my_port = enb_properties->ru_config[j]->local_port;
(eth_params+j)->remote_addr = enb_properties->ru_config[j]->remote_address;
(eth_params+j)->remote_port = enb_properties->ru_config[j]->remote_port;
if (enb_properties->ru_config[j]->raw == 1) {
(eth_params+j)->transp_preference = ETH_RAW_MODE;
ru_if_in[j] = REMOTE_IF5;
node_function[j] = NGFI_RRU_IF5;
} else if (enb_properties->ru_config[j]->rawif4p5 == 1) {
(eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE;
ru_if_in[j] = REMOTE_IF4p5;
node_function[j] = NGFI_RRU_IF4p5;
} else if (enb_properties->ru_config[j]->udpif4p5 == 1) {
(eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE;
ru_if_in[j] = REMOTE_IF4p5;
node_function[j] = NGFI_RRU_IF4p5;
} else if (enb_properties->ru_config[j]->rawif5_mobipass == 1) {
(eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS;
ru_if_in[j] = REMOTE_IF5;
LOG_E(EMU,"Don't use 8-bit IF5 format with oaisim, please change in configuration file\n");
} else {
(eth_params+j)->transp_preference = ETH_UDP_MODE;
ru_if_in[j] = REMOTE_IF5;
node_function[j] = NGFI_RRU_IF5;
}
node_timing[j] = synch_to_ext_device;
if (enb_properties->number > 0) {
//Update some simulation parameters
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];
oai_emulation.info.extended_prefix_flag[0] = enb_properties->properties[0]->prefix_type[0];
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];
oai_emulation.info.N_RB_DL[0] = enb_properties->properties[0]->N_RB_DL[0];
LOG_E(EMU,"Please use only RRU with oaisim, remove eNB descriptors in configuration file\n");
exit(-1);
}
}*/
}
else {
printf("Please provide a configuration file\n");
exit(-1);
}
}
void check_and_adjust_params(void)
{
int32_t ret;
//int i,j;
if (oai_emulation.info.nb_ue_local + oai_emulation.info.nb_rn_local > NUMBER_OF_UE_MAX) {
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);
}
if (oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local > NUMBER_OF_eNB_MAX) {
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);
}
if (oai_emulation.info.nb_rn_local > NUMBER_OF_RN_MAX) {
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);
}
// 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");
ret = netlink_init();
if (ret < 0)
LOG_W(EMU,"[INIT] Netlink not available, careful ...\n");
/*
if (ethernet_flag == 1) {
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;
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();
}
} // ethernet flag
*/
//
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;
NB_RN_INST = oai_emulation.info.nb_rn_local + oai_emulation.info.nb_rn_remote;
NB_RU = oai_emulation.info.nb_ru_local + oai_emulation.info.nb_ru_remote;
#if defined(PDCP_USE_NETLINK_QUEUES) && defined(OPENAIR2)
pdcp_netlink_init();
#endif
if (NB_RN_INST > 0 ) {
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);
LOG_N(EMU,"Adjust the number of eNB inst (%d->%d) and UE inst (%d->%d)\n ",
NB_eNB_INST, NB_eNB_INST+NB_RN_INST,
NB_UE_INST, NB_UE_INST+NB_RN_INST);
NB_eNB_INST+=NB_RN_INST;
NB_UE_INST+=NB_RN_INST;
}
LOG_I(EMU,"Total number of UE %d (first local %d , num local %d, remote %d, relay %d) mobility %s \n",
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);
LOG_I(EMU,"Total number of eNB %d (local %d, remote %d, relay %d) mobility %s \n",
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);
}
#ifdef OPENAIR2
void init_omv(void)
{
if (oai_emulation.info.omv_enabled == 1) {
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" );
}
}
#endif
void init_seed(uint8_t set_seed)
{
if(set_seed) {
randominit (oai_emulation.info.seed);
set_taus_seed (oai_emulation.info.seed);
} else {
randominit (0);
set_taus_seed (0);
}
}
openair0_timestamp current_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs];
openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
openair0_timestamp last_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs];
openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
int ru_trx_start(openair0_device *device) {
return(0);
}
void ru_trx_end(openair0_device *device) {
return;
}
int ru_trx_stop(openair0_device *device) {
return(0);
}
int UE_trx_start(openair0_device *device) {
return(0);
}
void UE_trx_end(openair0_device *device) {
return;
}
int UE_trx_stop(openair0_device *device) {
return(0);
}
int ru_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
return(0);
}
int ru_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);
}
extern pthread_mutex_t subframe_mutex;
extern int subframe_ru_mask,subframe_UE_mask;
int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int ru_id = device->Mod_id;
int CC_id = device->CC_id;
int subframe;
int sample_count=0;
*ptimestamp = last_ru_rx_timestamp[ru_id][CC_id];
LOG_D(EMU,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
(unsigned long long)current_ru_rx_timestamp[ru_id][CC_id],
(unsigned long long)last_ru_rx_timestamp[ru_id][CC_id],
(int)((*ptimestamp/RC.ru[ru_id]->frame_parms.samples_per_tti)%10));
// if we're at a subframe boundary generate UL signals for this ru
while (sample_count<nsamps) {
while (current_ru_rx_timestamp[ru_id][CC_id]<
(nsamps+last_ru_rx_timestamp[ru_id][CC_id])) {
LOG_D(EMU,"RU: current TS %"PRIi64", last TS %"PRIi64", sleeping\n",current_ru_rx_timestamp[ru_id][CC_id],last_ru_rx_timestamp[ru_id][CC_id]);
usleep(500);
}
subframe = (last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10;
if (subframe_select(&RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms.frame_type == FDD) {
LOG_D(EMU,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
subframe,(unsigned long long)*ptimestamp,
(unsigned long long)current_ru_rx_timestamp[ru_id][CC_id]);
do_UL_sig(UE2RU,
enb_data,
ue_data,
subframe,
0, // abstraction_flag
&RC.ru[ru_id]->frame_parms,
0, // frame is only used for abstraction
ru_id,
CC_id);
}
last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
sample_count += RC.ru[ru_id]->frame_parms.samples_per_tti;
}
return(nsamps);
}
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
int UE_id = device->Mod_id;
int CC_id = device->CC_id;
int subframe;
int sample_count=0;
int read_size;
int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
*ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];
LOG_D(EMU,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
UE_id,
nsamps,
(unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
(unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
(int)(last_UE_rx_timestamp[UE_id][CC_id]%sptti),
cc);
if (nsamps < sptti)
read_size = nsamps;
else
read_size = sptti;
while (sample_count<nsamps) {
LOG_D(EMU,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
while (current_UE_rx_timestamp[UE_id][CC_id] <
(last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
LOG_D(EMU,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
usleep(500);
}
LOG_D(EMU,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
// if we cross a subframe-boundary
subframe = (last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10;
// tell top-level we are busy
pthread_mutex_lock(&subframe_mutex);
subframe_UE_mask|=(1<<UE_id);
LOG_D(EMU,"Setting UE_id %d mask to busy (%d)\n",UE_id,subframe_UE_mask);
pthread_mutex_unlock(&subframe_mutex);
LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n",
UE_id,subframe,(unsigned long long)*ptimestamp,
(unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
nsamps);
LOG_D(EMU,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n",
UE_id,nsamps,subframe,
(int)(last_UE_rx_timestamp[UE_id][CC_id]%sptti));
do_DL_sig(RU2UE,
enb_data,
ue_data,
subframe,
last_UE_rx_timestamp[UE_id][CC_id]%sptti,
sptti,
0, //abstraction_flag,
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
UE_id,
CC_id);
LOG_D(EMU,"UE %d: DL simulation 6: UE_trx_read @ TS %"PRIi64" (%"PRIi64")=> frame %d, subframe %d\n",
UE_id, current_UE_rx_timestamp[UE_id][CC_id],
last_UE_rx_timestamp[UE_id][CC_id],
(int)((last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
subframe);
last_UE_rx_timestamp[UE_id][CC_id] += read_size;
sample_count += read_size;
}
return(nsamps);
}
extern double ru_amp[NUMBER_OF_RU_MAX];
int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
int ru_id = device->Mod_id;
LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms;
pthread_mutex_lock(&subframe_mutex);
LOG_D(EMU,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,subframe_ru_mask);
pthread_mutex_unlock(&subframe_mutex);
// compute amplitude of TX signal from first symbol in subframe
// note: assumes that the packet is an entire subframe
ru_amp[ru_id] = 0;
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
ru_amp[ru_id] += (double)signal_energy((int32_t*)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
}
ru_amp[ru_id] = sqrt(ru_amp[ru_id]);
LOG_D(EMU,"Setting amp for RU %d to %f (%d)\n",ru_id,ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t*)buff[0],frame_parms->ofdm_symbol_size)));
// tell top-level we are done
pthread_mutex_lock(&subframe_mutex);
subframe_ru_mask|=(1<<ru_id);
LOG_D(EMU,"Setting RU %d to busy\n",ru_id);
pthread_mutex_unlock(&subframe_mutex);
return(nsamps);
}
int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
return(nsamps);
}
//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,
RC.ru[0]->nb_tx,
RC.ru[0]->nb_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,RC.ru[0]->nb_tx);
openair0_cfg[card].rx_num_channels=min(2,RC.ru[0]->nb_rx);
for (i=0; i<4; i++) {
openair0_cfg[card].rx_gain[i] = RC.ru[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]);
}
}
}
*/
void init_devices(void){
module_id_t UE_id, ru_id;
uint8_t CC_id;
RU_t *ru;
// allocate memory for RU if not already done
if (RC.ru==NULL) RC.ru = (RU_t**)malloc(RC.nb_RU*sizeof(RU_t*));
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
LOG_I(EMU,"Initiaizing rfdevice for RU %d\n",ru_id);
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t*)malloc(sizeof(RU_t));
ru = RC.ru[ru_id];
ru->rfdevice.Mod_id = ru_id;
ru->rfdevice.CC_id = 0;
ru->rfdevice.trx_start_func = ru_trx_start;
ru->rfdevice.trx_read_func = ru_trx_read;
ru->rfdevice.trx_write_func = ru_trx_write;
ru->rfdevice.trx_end_func = ru_trx_end;
ru->rfdevice.trx_stop_func = ru_trx_stop;
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
last_ru_rx_timestamp[ru_id][0] = 0;
}
if (PHY_vars_UE_g==NULL) {
PHY_vars_UE_g = (PHY_VARS_UE ***)malloc((1+NB_UE_INST)*sizeof(PHY_VARS_UE*));
for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
printf("Initializing UE %d\n",UE_id);
PHY_vars_UE_g[UE_id] = (PHY_VARS_UE **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_UE*));
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
PHY_vars_UE_g[UE_id][CC_id] = (PHY_VARS_UE *)malloc(sizeof(PHY_VARS_UE));
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;
last_UE_rx_timestamp[UE_id][CC_id] = 0;
}
}
}
}
void init_ocm(void)
{
module_id_t UE_id, ru_id;
int CC_id;
/* Added for PHY abstraction */
/* TODO: frame_type is unused, is it intended? */
//char* frame_type = "unknown";
LTE_DL_FRAME_PARMS *fp = &RC.ru[0]->frame_parms;
#if 0
switch (fp->frame_type) {
case FDD:
frame_type = "FDD";
break;
case TDD:
frame_type = "TDD";
break;
}
#endif
if (abstraction_flag) {
get_beta_map();
get_MIESM_param();
//load_pbch_desc();
}
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
enb_data[ru_id] = (node_desc_t *)malloc(sizeof(node_desc_t));
init_enb(enb_data[ru_id],oai_emulation.environment_system_config.antenna.eNB_antenna);
}
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
ue_data[UE_id] = (node_desc_t *)malloc(sizeof(node_desc_t));
init_ue(ue_data[UE_id],oai_emulation.environment_system_config.antenna.UE_antenna);
}
if ((oai_emulation.info.ocm_enabled == 1)&& (ethernet_flag == 0 ) &&
(oai_emulation.environment_system_config.fading.shadowing.decorrelation_distance_m>0) &&
(oai_emulation.environment_system_config.fading.shadowing.variance_dB>0)) {
// init SF map here!!!
map1 =(int)oai_emulation.topology_config.area.x_m;
map2 =(int)oai_emulation.topology_config.area.y_m;
ShaF = init_SF(map1,map2,oai_emulation.environment_system_config.fading.shadowing.decorrelation_distance_m,oai_emulation.environment_system_config.fading.shadowing.variance_dB);
// size of area to generate shadow fading map
LOG_D(EMU,"Simulation area x=%f, y=%f\n",
oai_emulation.topology_config.area.x_m,
oai_emulation.topology_config.area.y_m);
}
if (abstraction_flag == 0)
init_channel_vars (fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
// initialize channel descriptors
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
LOG_I(OCM,"Initializing channel (%s, %d) from RU %d to UE %d\n", oai_emulation.environment_system_config.fading.small_scale.selected_option,
map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), ru_id, UE_id);
RU2UE[ru_id][UE_id][CC_id] =
new_channel_desc_scm(RC.ru[ru_id]->nb_tx,
PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx,
map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option),
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms.N_RB_DL),
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms.N_RB_DL),
forgetting_factor,
0,
0);
random_channel(RU2UE[ru_id][UE_id][CC_id],abstraction_flag);
LOG_D(OCM,"[SIM] Initializing channel (%s, %d) from UE %d to ru %d\n", oai_emulation.environment_system_config.fading.small_scale.selected_option,
map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option),UE_id, ru_id);
UE2RU[UE_id][ru_id][CC_id] =
new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
RC.ru[ru_id]->nb_rx,
map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option),
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms.N_RB_UL),
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms.N_RB_UL),
forgetting_factor,
0,
0);
random_channel(UE2RU[UE_id][ru_id][CC_id],abstraction_flag);
// to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed.
//UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id];
}
}
}
}
void init_otg_pdcp_buffer(void)
{
module_id_t i;
otg_pdcp_buffer = malloc((NB_UE_INST + NB_eNB_INST) * sizeof(Packet_OTG_List_t));
for (i = 0; i < NB_UE_INST + NB_eNB_INST; i++) {
pkt_list_init(&(otg_pdcp_buffer[i]));
//LOG_I(EMU,"HEAD of otg_pdcp_buffer[%d] is %p\n", i, pkt_list_get_head(&(otg_pdcp_buffer[i])));
}
}
void update_omg (frame_t frameP)
{
module_id_t UE_id, eNB_id;
int new_omg_model;
if ((frameP % omg_period) == 0 ) { // call OMG every 10ms
update_nodes(oai_emulation.info.time_s);
display_node_list(enb_node_list);
display_node_list(ue_node_list);
if (oai_emulation.info.omg_model_ue >= MAX_NUM_MOB_TYPES) { // mix mobility model
for(UE_id=oai_emulation.info.first_ue_local; UE_id<(oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local); UE_id++) {
new_omg_model = randomgen(STATIC,RWALK);
LOG_D(OMG, "[UE] Node of ID %d is changing mobility generator ->%d \n", UE_id, new_omg_model);
// reset the mobility model for a specific node
set_new_mob_type (UE_id, UE, new_omg_model, oai_emulation.info.time_s);
}
}
if (oai_emulation.info.omg_model_enb >= MAX_NUM_MOB_TYPES) { // mix mobility model
for (eNB_id = oai_emulation.info.first_enb_local; eNB_id < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local); eNB_id++) {
new_omg_model = randomgen (STATIC, RWALK);
LOG_D (OMG,"[eNB] Node of ID %d is changing mobility generator ->%d \n", eNB_id, new_omg_model);
// reset the mobility model for a specific node
set_new_mob_type (eNB_id, eNB, new_omg_model, oai_emulation.info.time_s);
}
}
}
}
void update_omg_ocm()
{
enb_node_list=get_current_positions(oai_emulation.info.omg_model_enb, eNB, oai_emulation.info.time_s);
ue_node_list=get_current_positions(oai_emulation.info.omg_model_ue, UE, oai_emulation.info.time_s);
}
void update_ocm()
{
module_id_t UE_id, ru_id;
int CC_id;
/* check if the openair channel model is activated used for PHY abstraction : path loss*/
if ((oai_emulation.info.ocm_enabled == 1)&& (ethernet_flag == 0 )) {
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++)
enb_data[ru_id]->tx_power_dBm = RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++)
ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm[0];
//LOG_D(OMG," extracting position of eNb...\n");
//display_node_list(enb_node_list);
// display_node_list(ue_node_list);
//extract_position(enb_node_list, enb_data, RC.nb_RU);
//extract_position_fixed_enb(enb_data, NB_eNB_INST,frame);
//LOG_D(OMG," extracting position of UE...\n");
// if (oai_emulation.info.omg_model_ue == TRACE)
//extract_position(ue_node_list, ue_data, NB_UE_INST);
/* if (frame % 50 == 0)
LOG_N(OCM,"Path loss for TTI %d : \n", frame);
*/
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
calc_path_loss (enb_data[ru_id], ue_data[UE_id], RU2UE[ru_id][UE_id][CC_id], oai_emulation.environment_system_config,ShaF);
//calc_path_loss (enb_data[ru_id], ue_data[UE_id], RU2UE[ru_id][UE_id], oai_emulation.environment_system_config,0);
UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = RU2UE[ru_id][UE_id][CC_id]->path_loss_dB;
// if (frame % 50 == 0)
LOG_D(OCM,"Path loss (CCid %d) between eNB %d at (%f,%f) and UE %d at (%f,%f) is %f, angle %f\n",
CC_id,ru_id,enb_data[ru_id]->x,enb_data[ru_id]->y,UE_id,ue_data[UE_id]->x,ue_data[UE_id]->y,
RU2UE[ru_id][UE_id][CC_id]->path_loss_dB, RU2UE[ru_id][UE_id][CC_id]->aoa);
//double dx, dy, distance;
//dx = enb_data[ru_id]->x - ue_data[UE_id]->x;
//dy = enb_data[ru_id]->y - ue_data[UE_id]->y;
//distance = sqrt(dx * dx + dy * dy);
/*LOG_D(LOCALIZE, " OCM distance between eNB %d at (%f,%f) and UE %d at (%f,%f) is %f \n",
ru_id, enb_data[ru_id]->x,enb_data[ru_id]->y,
UE_id, ue_data[UE_id]->x,ue_data[UE_id]->y,
distance);*/
}
}
}
}
else {
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
AssertFatal(RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
AssertFatal(UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
if (ru_id == (UE_id % RC.nb_RU)) {
RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
} else {
RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
}
LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
}
}
}
}
}
#ifdef OPENAIR2
void update_otg_eNB(module_id_t enb_module_idP, unsigned int ctime)
{
#if defined(USER_MODE) && defined(OAI_EMU)
//int rrc_state=0;
/*
if (oai_emulation.info.otg_enabled ==1 ) {
int dst_id, app_id;
Packet_otg_elt_t *otg_pkt;
for (dst_id = 0; dst_id < NUMBER_OF_UE_MAX; dst_id++) {
for_times += 1;
// generate traffic if the ue is rrc reconfigured state
//if ((rrc_state=mac_eNB_get_rrc_status(enb_module_idP, dst_id)) > 2 //RRC_CONNECTED
{
if (mac_eNB_get_rrc_status(enb_module_idP, oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_idP][dst_id]) > 2 ){
if_times += 1;
for (app_id=0; app_id<MAX_NUM_APPLICATION; app_id++) {
otg_pkt = malloc (sizeof(Packet_otg_elt_t));
(otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen(enb_module_idP, dst_id + NB_eNB_INST, app_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
otg_times += 1;
(otg_pkt->otg_pkt).rb_id = DTCH-2; // app could be binded to a given DRB
(otg_pkt->otg_pkt).module_id = enb_module_idP;
(otg_pkt->otg_pkt).dst_id = dst_id;
(otg_pkt->otg_pkt).is_ue = 0;
(otg_pkt->otg_pkt).mode = PDCP_TRANSMISSION_MODE_DATA;
//Adding the packet to the OTG-PDCP buffer
pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[enb_module_idP]));
LOG_D(EMU,"[eNB %d] ADD pkt to OTG buffer with size %d for dst %d on rb_id %d for app id %d \n",
(otg_pkt->otg_pkt).module_id, otg_pkt->otg_pkt.sdu_buffer_size, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id, app_id);
} else {
free(otg_pkt);
otg_pkt=NULL;
}
}
}
}
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
mbms_service_id_t service_id;
mbms_session_id_t session_id;
rb_id_t rb_id;
// MBSM multicast traffic
if (ctime >= 500 ) {// only generate when UE can receive MTCH (need to control this value)
for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount
for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH
if (pdcp_mbms_array_eNB[enb_module_idP][service_id][session_id].instanciated_instance == TRUE) { // this service/session is configured
otg_pkt = malloc (sizeof(Packet_otg_elt_t));
// LOG_T(OTG,"multicast packet gen for (service/mch %d, session/lcid %d, rb_id %d)\n", service_id, session_id, service_id*maxSessionPerPMCH + session_id);
rb_id = pdcp_mbms_array_eNB[enb_module_idP][service_id][session_id].rb_id;
(otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen_multicast(enb_module_idP, session_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
(otg_pkt->otg_pkt).rb_id = rb_id;
(otg_pkt->otg_pkt).module_id = enb_module_idP;
(otg_pkt->otg_pkt).dst_id = session_id;
(otg_pkt->otg_pkt).is_ue = FALSE;
//Adding the packet to the OTG-PDCP buffer
(otg_pkt->otg_pkt).mode = PDCP_TRANSMISSION_MODE_TRANSPARENT;
pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[enb_module_idP]));
LOG_D(EMU, "[eNB %d] ADD packet (%p) multicast to OTG buffer for dst %d on rb_id %d\n",
(otg_pkt->otg_pkt).module_id, otg_pkt, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
} else {
//LOG_I(EMU, "OTG returns null \n");
free(otg_pkt);
otg_pkt=NULL;
}
*/
// old version
/* // MBSM multicast traffic
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
if (frame >= 46) {// only generate when UE can receive MTCH (need to control this value)
for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount
for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH
// LOG_I(OTG,"DUY:frame %d, pdcp_mbms_array[module_id][rb_id].instanciated_instance is %d\n",frame,pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].instanciated_instance);
if ((pdcp_mbms_array[module_idP][service_id*maxSessionPerPMCH + session_id].instanciated_instance== module_idP + 1) && (eNB_flag == 1)){ // this service/session is configured
// LOG_T(OTG,"multicast packet gen for (service/mch %d, session/lcid %d)\n", service_id, session_id);
// Duy add
LOG_I(OTG, "frame %d, multicast packet gen for (service/mch %d, session/lcid %d, rb_id %d)\n",frame, service_id, session_id,service_id*maxSessionPerPMCH + session_id);
// end Duy add
rb_id = pdcp_mbms_array[module_id][service_id*maxSessionPerPMCH + session_id].rb_id;
otg_pkt=(uint8_t*) packet_gen_multicast(module_idP, session_id, ctime, &pkt_size);
if (otg_pkt != NULL) {
LOG_D(OTG,"[eNB %d] sending a multicast packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n", eNB_index, module_idP, rb_id, module_idP, session_id, pkt_size);
pdcp_data_req(module_id, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, pkt_size, otg_pkt,PDCP_TM);
free(otg_pkt);
}
}
}
}
} // end multicast traffic
#endif
*/
/*
}
}
}
} // end multicast traffic
*/
#endif
}
#else
#if 0 // defined(EXMIMO) || defined(OAI_USRP)
if (otg_enabled==1) {
ctime = frame * 100;
for (dst_id = 0; dst_id < NUMBER_OF_UE_MAX; dst_id++) {
if (mac_get_rrc_status(eNB_index, eNB_flag, dst_id ) > 2) {
otg_pkt = malloc (sizeof(Packet_otg_elt_t));
(otg_pkt->otg_pkt).sdu_buffer = packet_gen(module_instP, dst_id, ctime, &pkt_size);
if (otg_pkt != NULL) {
rb_id = DTCH-2;
(otg_pkt->otg_pkt).rb_id = rb_id;
(otg_pkt->otg_pkt).module_id = module_idP;
(otg_pkt->otg_pkt).is_ue = FALSE;
(otg_pkt->otg_pkt).mode = PDCP_TRANSMISSION_MODE_DATA;
//Adding the packet to the OTG-PDCP buffer
pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[module_idP]));
LOG_D(EMU, "[eNB %d] ADD pkt to OTG buffer for dst %d on rb_id %d\n", (otg_pkt->otg_pkt).module_id, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
} else {
//LOG_I(EMU, "OTG returns null \n");
free(otg_pkt);
otg_pkt=NULL;
}
}
}
}
#endif
}
void update_otg_UE(module_id_t ue_mod_idP, unsigned int ctime)
{
}
#endif
int init_slot_isr(void)
{
if (oai_emulation.info.slot_isr) {
struct itimerspec its;
int sfd;
sfd = timerfd_create(CLOCK_REALTIME, 0);
if (sfd == -1) {
LOG_E(EMU, "Failed in timerfd_create (%d:%s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
/* Start the timer */
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 500 * 1000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timerfd_settime(sfd, TFD_TIMER_ABSTIME, &its, NULL) == -1) {
LOG_E(EMU, "Failed in timer_settime (%d:%s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
oai_emulation.info.slot_sfd = sfd;
}
return 0;
}
void wait_for_slot_isr(void)
{
uint64_t exp;
ssize_t res;
if (oai_emulation.info.slot_sfd > 0) {
res = read(oai_emulation.info.slot_sfd, &exp, sizeof(exp));
if ((res < 0) || (res != sizeof(exp))) {
LOG_E(EMU, "Failed in read (%d:%s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
}
void exit_fun(const char* s)
{
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, 2);
fprintf(stderr, "Error: %s. Exiting!\n",s);
exit (-1);
}
void init_time()
{
clock_gettime (CLOCK_REALTIME, &time_spec);
time_now = (unsigned long) time_spec.tv_nsec;
td_avg = 0;
sleep_time_us = SLEEP_STEP_US;
td_avg = TARGET_SF_TIME_NS;
}
// dummy function
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {
return(0);
}
/*
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) {
return(0);
}
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) {
return(0);
}
*/