1916 lines
65 KiB
C
1916 lines
65 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.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
|
|
*/
|
|
|
|
/*! \file oaisim.c
|
|
* \brief oaisim top level
|
|
* \author Navid Nikaein
|
|
* \date 2013-2015
|
|
* \version 1.0
|
|
* \company Eurecom
|
|
* \email: openair_tech@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <cblas.h>
|
|
#include <execinfo.h>
|
|
|
|
#include "event_handler.h"
|
|
#include "SIMULATION/RF/defs.h"
|
|
#include "PHY/types.h"
|
|
#include "PHY/defs.h"
|
|
#include "PHY/LTE_TRANSPORT/proto.h"
|
|
#include "PHY/vars.h"
|
|
|
|
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
|
|
|
//#ifdef OPENAIR2
|
|
#include "LAYER2/MAC/defs.h"
|
|
#include "LAYER2/MAC/proto.h"
|
|
#include "LAYER2/MAC/vars.h"
|
|
#include "pdcp.h"
|
|
#include "RRC/LITE/vars.h"
|
|
#include "RRC/NAS/nas_config.h"
|
|
|
|
#include "SCHED/defs.h"
|
|
#include "SCHED/vars.h"
|
|
|
|
|
|
#include "PHY/TOOLS/lte_phy_scope.h"
|
|
|
|
|
|
#ifdef SMBV
|
|
// Rohde&Schwarz SMBV100A vector signal generator
|
|
#include "PHY/TOOLS/smbv.h"
|
|
char smbv_fname[] = "smbv_config_file.smbv";
|
|
unsigned short smbv_nframes = 4; // how many frames to configure 1,..,4
|
|
unsigned short config_frames[4] = {2,9,11,13};
|
|
unsigned char smbv_frame_cnt = 0;
|
|
uint8_t config_smbv = 0;
|
|
char smbv_ip[16];
|
|
#endif
|
|
|
|
#if defined(FLEXRAN_AGENT_SB_IF)
|
|
# include "flexran_agent.h"
|
|
#endif
|
|
|
|
|
|
#include "oaisim_functions.h"
|
|
|
|
#include "oaisim.h"
|
|
#include "oaisim_config.h"
|
|
#include "UTIL/OCG/OCG_extern.h"
|
|
#include "cor_SF_sim.h"
|
|
#include "UTIL/OMG/omg_constants.h"
|
|
#include "UTIL/FIFO/pad_list.h"
|
|
#include "enb_app.h"
|
|
|
|
#include "../PROC/interface.h"
|
|
#include "../PROC/channel_sim_proc.h"
|
|
#include "../PROC/Tsync.h"
|
|
#include "../PROC/Process.h"
|
|
|
|
#include "UTIL/LOG/vcd_signal_dumper.h"
|
|
#include "UTIL/OTG/otg_kpi.h"
|
|
#include "assertions.h"
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
# include "intertask_interface.h"
|
|
# include "create_tasks.h"
|
|
#endif
|
|
|
|
#include "T.h"
|
|
|
|
/*
|
|
DCI0_5MHz_TDD0_t UL_alloc_pdu;
|
|
DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu;
|
|
DCI2_5MHz_2A_L10PRB_TDD_t DLSCH_alloc_pdu1;
|
|
DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2;
|
|
*/
|
|
|
|
#define UL_RB_ALLOC computeRIV(lte_frame_parms->N_RB_UL,0,24)
|
|
#define CCCH_RB_ALLOC computeRIV(lte_frame_parms->N_RB_UL,0,3)
|
|
#define RA_RB_ALLOC computeRIV(lte_frame_parms->N_RB_UL,0,3)
|
|
#define DLSCH_RB_ALLOC 0x1fff
|
|
|
|
#define DECOR_DIST 100
|
|
#define SF_VAR 10
|
|
|
|
//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 */
|
|
|
|
uint8_t usim_test = 0;
|
|
|
|
frame_t frame = 0;
|
|
char stats_buffer[16384];
|
|
channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
|
|
channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
|
|
//Added for PHY abstraction
|
|
node_desc_t *enb_data[NUMBER_OF_eNB_MAX];
|
|
node_desc_t *ue_data[NUMBER_OF_UE_MAX];
|
|
|
|
pthread_cond_t sync_cond;
|
|
pthread_mutex_t sync_mutex;
|
|
int sync_var=-1;
|
|
|
|
pthread_mutex_t subframe_mutex;
|
|
int subframe_eNB_mask=0,subframe_UE_mask=0;
|
|
|
|
openair0_config_t openair0_cfg[MAX_CARDS];
|
|
uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
|
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
|
openair0_rf_map rf_map[MAX_NUM_CCs];
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
volatile int start_eNB = 0;
|
|
volatile int start_UE = 0;
|
|
#endif
|
|
volatile int oai_exit = 0;
|
|
|
|
|
|
//int32_t **rxdata;
|
|
//int32_t **txdata;
|
|
|
|
|
|
// Added for PHY abstraction
|
|
extern node_list* ue_node_list;
|
|
extern node_list* enb_node_list;
|
|
extern int pdcp_period, omg_period;
|
|
|
|
extern double **s_re, **s_im, **r_re, **r_im, **r_re0, **r_im0;
|
|
int map1, map2;
|
|
extern double **ShaF;
|
|
double snr_dB, sinr_dB, snr_direction; //,sinr_direction;
|
|
extern double snr_step;
|
|
extern uint8_t set_sinr;
|
|
extern uint8_t ue_connection_test;
|
|
extern uint8_t set_seed;
|
|
extern uint8_t target_dl_mcs;
|
|
extern uint8_t target_ul_mcs;
|
|
extern uint8_t abstraction_flag;
|
|
extern uint8_t ethernet_flag;
|
|
extern uint16_t Nid_cell;
|
|
|
|
extern LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
|
|
|
|
|
|
|
|
//#ifdef XFORMS
|
|
int otg_enabled;
|
|
int xforms=0;
|
|
//#endif
|
|
|
|
time_stats_t oaisim_stats;
|
|
time_stats_t oaisim_stats_f;
|
|
time_stats_t dl_chan_stats;
|
|
time_stats_t ul_chan_stats;
|
|
|
|
// this should reflect the channel models in openair1/SIMULATION/TOOLS/defs.h
|
|
mapping small_scale_names[] = {
|
|
{ "custom", custom }, { "SCM_A", SCM_A },
|
|
{ "SCM_B", SCM_B }, { "SCM_C", SCM_C },
|
|
{ "SCM_D", SCM_D }, { "EPA", EPA },
|
|
{ "EVA", EVA }, { "ETU", ETU },
|
|
{ "MBSFN", MBSFN }, { "Rayleigh8", Rayleigh8 },
|
|
{ "Rayleigh1", Rayleigh1 }, { "Rayleigh1_800", Rayleigh1_800 },
|
|
{ "Rayleigh1_corr", Rayleigh1_corr }, { "Rayleigh1_anticorr", Rayleigh1_anticorr },
|
|
{ "Rice8", Rice8 }, { "Rice1", Rice1 }, { "Rice1_corr", Rice1_corr },
|
|
{ "Rice1_anticorr", Rice1_anticorr }, { "AWGN", AWGN }, { NULL,-1 }
|
|
};
|
|
#if !defined(ENABLE_ITTI)
|
|
static void *
|
|
sigh (void *arg);
|
|
#endif
|
|
void
|
|
oai_shutdown (void);
|
|
|
|
void reset_opp_meas_oaisim (void);
|
|
|
|
void
|
|
help (void)
|
|
{
|
|
printf ("Usage: oaisim -h -a -F -C tdd_config -K [log_file] -V [vcd_file] -R N_RB_DL -e -x transmission_mode -m target_dl_mcs -r(ate_adaptation) -n n_frames -s snr_dB -k ricean_factor -t max_delay -f forgetting factor -A channel_model -z cooperation_flag -u nb_local_ue -U UE mobility -b nb_local_enb -B eNB_mobility -M ethernet_flag -p nb_master -g multicast_group -l log_level -c ocg_enable -T traffic model -D multicast network device\n");
|
|
|
|
printf ("-h provides this help message!\n");
|
|
printf ("-a Activates PHY abstraction mode\n");
|
|
printf ("-A set the multipath channel simulation, options are: SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr,Rayleigh1_anticorr, Rice8,, Rice1, AWGN \n");
|
|
printf ("-b Set the number of local eNB\n");
|
|
printf ("-B Set the mobility model for eNB, options are: STATIC, RWP, RWALK, \n");
|
|
printf ("-c [1,2,3,4] Activate the config generator (OCG) to process the scenario descriptor, or give the scenario manually: -c template_1.xml \n");
|
|
printf ("-C [0-6] Sets TDD configuration\n");
|
|
printf ("-e Activates extended prefix mode\n");
|
|
printf ("-E Random number generator seed\n");
|
|
printf ("-f Set the forgetting factor for time-variation\n");
|
|
printf ("-F Activates FDD transmission (TDD is default)\n");
|
|
printf ("-g Set multicast group ID (0,1,2,3) - valid if M is set\n");
|
|
printf ("-G Enable background traffic \n");
|
|
printf ("-H Enable handover operation (default disabled) \n");
|
|
printf ("-I Enable CLI interface (to connect use telnet localhost 1352)\n");
|
|
printf ("-k Set the Ricean factor (linear)\n");
|
|
printf ("-K [log_file] Enable ITTI logging into log_file\n");
|
|
printf ("-l Set the global log level (8:trace, 7:debug, 6:info, 4:warn, 3:error) \n");
|
|
printf ("-L [0-1] 0 to disable new link adaptation, 1 to enable new link adapatation\n");
|
|
printf ("-m Gives a fixed DL mcs for eNB scheduler\n");
|
|
printf ("-M Set the machine ID for Ethernet-based emulation\n");
|
|
printf ("-n Set the number of frames for the simulation\n");
|
|
printf ("-O [enb_conf_file] eNB configuration file name\n");
|
|
printf ("-p Set the total number of machine in emulation - valid if M is set\n");
|
|
printf ("-P [trace type] Enable protocol analyzer. Possible values for OPT:\n");
|
|
printf (" - wireshark: Enable tracing of layers above PHY using an UDP socket\n");
|
|
printf (" - pcap: Enable tracing of layers above PHY to a pcap file\n");
|
|
printf (" - tshark: Not implemented yet\n");
|
|
printf ("-q Enable Openair performance profiler \n");
|
|
printf ("-Q Activate and set the MBMS service: 0 : not used (default eMBMS disabled), 1: eMBMS and RRC Connection enabled, 2: eMBMS relaying and RRC Connection enabled, 3: eMBMS enabled, RRC Connection disabled, 4: eMBMS relaying enabled, RRC Connection disabled\n");
|
|
printf ("-R [6,15,25,50,75,100] Sets N_RB_DL\n");
|
|
printf ("-r Activates rate adaptation (DL for now)\n");
|
|
printf ("-s snr_dB set a fixed (average) SNR, this deactivates the openair channel model generator (OCM)\n");
|
|
printf ("-S snir_dB set a fixed (average) SNIR, this deactivates the openair channel model generator (OCM)\n");
|
|
printf ("-t Gives a fixed UL mcs for eNB scheduler\n");
|
|
printf ("-T activate the traffic generator. Valide options are m2m,scbr,mcbr,bcbr,auto_pilot,bicycle_race,open_arena,team_fortress,m2m_traffic,auto_pilot_l,auto_pilot_m,auto_pilot_h,auto_pilot_e,virtual_game_l,virtual_game_m,virtual_game_h,virtual_game_f,alarm_humidity,alarm_smoke,alarm_temperature,openarena_dl,openarena_ul,voip_g711,voip_g729,video_vbr_10mbps,video_vbr_4mbps,video_vbr_2mbp,video_vbr_768kbps,video_vbr_384kbps,video_vbr_192kpbs,background_users\n");
|
|
printf ("-u Set the number of local UE\n");
|
|
printf ("-U Set the mobility model for UE, options are: STATIC, RWP, RWALK\n");
|
|
printf ("-V [vcd_file] Enable VCD dump into vcd_file\n");
|
|
printf ("-w number of CBA groups, if not specified or zero, CBA is inactive\n");
|
|
#ifdef SMBV
|
|
printf ("-W IP address to connect to Rohde&Schwarz SMBV100A and configure SMBV from config file. -W0 uses default IP 192.168.12.201\n");
|
|
#else
|
|
printf ("-W [Rohde&Schwarz SMBV100A functions disabled. Recompile with SMBV=1]\n");
|
|
#endif
|
|
printf ("-x deprecated. Set the transmission mode in config file!\n");
|
|
printf ("-y Set the number of receive antennas at the UE (1 or 2)\n");
|
|
printf ("-Y Set the global log verbosity (none, low, medium, high, full) \n");
|
|
printf ("-z Set the cooperation flag (0 for no cooperation, 1 for delay diversity and 2 for distributed alamouti\n");
|
|
printf ("-Z Reserved\n");
|
|
printf ("--xforms Activate the grapical scope\n");
|
|
|
|
#if T_TRACER
|
|
printf ("--T_port [port] use given port\n");
|
|
printf ("--T_nowait don't wait for tracer, start immediately\n");
|
|
printf ("--T_dont_fork to ease debugging with gdb\n");
|
|
#endif
|
|
}
|
|
|
|
pthread_t log_thread;
|
|
|
|
void
|
|
log_thread_init (void)
|
|
{
|
|
//create log_list
|
|
//log_list_init(&log_list);
|
|
#ifndef LOG_NO_THREAD
|
|
|
|
log_shutdown = 0;
|
|
|
|
if ((pthread_mutex_init (&log_lock, NULL) != 0)
|
|
|| (pthread_cond_init (&log_notify, NULL) != 0)) {
|
|
return;
|
|
}
|
|
|
|
if (pthread_create (&log_thread, NULL, log_thread_function, (void*) NULL)
|
|
!= 0) {
|
|
log_thread_finalize ();
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
//Call it after the last LOG call
|
|
int
|
|
log_thread_finalize (void)
|
|
{
|
|
int err = 0;
|
|
|
|
#ifndef LOG_NO_THREAD
|
|
|
|
if (pthread_mutex_lock (&log_lock) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
log_shutdown = 1;
|
|
|
|
/* Wake up LOG thread */
|
|
if ((pthread_cond_broadcast (&log_notify) != 0)
|
|
|| (pthread_mutex_unlock (&log_lock) != 0)) {
|
|
err = -1;
|
|
}
|
|
|
|
if (pthread_join (log_thread, NULL) != 0) {
|
|
err = -1;
|
|
}
|
|
|
|
if (pthread_mutex_unlock (&log_lock) != 0) {
|
|
err = -1;
|
|
}
|
|
|
|
if (!err) {
|
|
//log_list_free(&log_list);
|
|
pthread_mutex_lock (&log_lock);
|
|
pthread_mutex_destroy (&log_lock);
|
|
pthread_cond_destroy (&log_notify);
|
|
}
|
|
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
static void set_cli_start(module_id_t module_idP, uint8_t start)
|
|
{
|
|
if (module_idP < NB_eNB_INST) {
|
|
oai_emulation.info.cli_start_enb[module_idP] = start;
|
|
} else {
|
|
oai_emulation.info.cli_start_ue[module_idP - NB_eNB_INST] = start;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef OPENAIR2
|
|
int omv_write(int pfd, node_list* enb_node_list, node_list* ue_node_list, Data_Flow_Unit omv_data)
|
|
{
|
|
module_id_t i, j;
|
|
omv_data.end = 0;
|
|
|
|
//omv_data.total_num_nodes = NB_UE_INST + NB_eNB_INST;
|
|
for (i = 0; i < NB_eNB_INST; i++) {
|
|
if (enb_node_list != NULL) {
|
|
omv_data.geo[i].x = (enb_node_list->node->x_pos < 0.0) ? 0.0 : enb_node_list->node->x_pos;
|
|
omv_data.geo[i].y = (enb_node_list->node->y_pos < 0.0) ? 0.0 : enb_node_list->node->y_pos;
|
|
omv_data.geo[i].z = 1.0;
|
|
omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_enb;
|
|
omv_data.geo[i].node_type = 0; //eNB
|
|
enb_node_list = enb_node_list->next;
|
|
omv_data.geo[i].Neighbors = 0;
|
|
|
|
for (j = NB_eNB_INST; j < NB_UE_INST + NB_eNB_INST; j++) {
|
|
if (is_UE_active (i, j - NB_eNB_INST) == 1) {
|
|
omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
|
|
omv_data.geo[i].Neighbors++;
|
|
LOG_D(
|
|
OMG,
|
|
"[eNB %d][UE %d] is_UE_active(i,j) %d geo (x%d, y%d) num neighbors %d\n", i, j-NB_eNB_INST, is_UE_active(i,j-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = NB_eNB_INST; i < NB_UE_INST + NB_eNB_INST; i++) {
|
|
if (ue_node_list != NULL) {
|
|
omv_data.geo[i].x = (ue_node_list->node->x_pos < 0.0) ? 0.0 : ue_node_list->node->x_pos;
|
|
omv_data.geo[i].y = (ue_node_list->node->y_pos < 0.0) ? 0.0 : ue_node_list->node->y_pos;
|
|
omv_data.geo[i].z = 1.0;
|
|
omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_ue;
|
|
omv_data.geo[i].node_type = 1; //UE
|
|
//trial
|
|
omv_data.geo[i].state = 1;
|
|
omv_data.geo[i].rnti = 88;
|
|
omv_data.geo[i].connected_eNB = 0;
|
|
omv_data.geo[i].RSRP = 66;
|
|
omv_data.geo[i].RSRQ = 55;
|
|
omv_data.geo[i].Pathloss = 44;
|
|
omv_data.geo[i].RSSI[0] = 33;
|
|
omv_data.geo[i].RSSI[1] = 22;
|
|
|
|
if ((sizeof(omv_data.geo[0].RSSI) / sizeof(omv_data.geo[0].RSSI[0])) > 2) {
|
|
omv_data.geo[i].RSSI[2] = 11;
|
|
}
|
|
|
|
ue_node_list = ue_node_list->next;
|
|
omv_data.geo[i].Neighbors = 0;
|
|
|
|
for (j = 0; j < NB_eNB_INST; j++) {
|
|
if (is_UE_active (j, i - NB_eNB_INST) == 1) {
|
|
omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
|
|
omv_data.geo[i].Neighbors++;
|
|
LOG_D(
|
|
OMG,
|
|
"[UE %d][eNB %d] is_UE_active %d geo (x%d, y%d) num neighbors %d\n", i-NB_eNB_INST, j, is_UE_active(j,i-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG_E(OMG, "pfd %d \n", pfd);
|
|
|
|
if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
|
|
perror ("write omv failed");
|
|
|
|
return 1;
|
|
}
|
|
|
|
void omv_end(int pfd, Data_Flow_Unit omv_data)
|
|
{
|
|
omv_data.end = 1;
|
|
|
|
if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
|
|
perror ("write omv failed");
|
|
}
|
|
#endif
|
|
|
|
#ifdef OPENAIR2
|
|
int pfd[2]; // fd for omv : fixme: this could be a local var
|
|
#endif
|
|
|
|
#ifdef OPENAIR2
|
|
static Data_Flow_Unit omv_data;
|
|
#endif //ALU
|
|
static module_id_t UE_inst = 0;
|
|
static module_id_t eNB_inst = 0;
|
|
|
|
Packet_OTG_List_t *otg_pdcp_buffer;
|
|
|
|
typedef enum l2l1_task_state_e {
|
|
L2L1_WAITTING, L2L1_RUNNING, L2L1_TERMINATED,
|
|
} l2l1_task_state_t;
|
|
|
|
l2l1_task_state_t l2l1_state = L2L1_WAITTING;
|
|
|
|
extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
|
|
extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
void *
|
|
l2l1_task (void *args_p)
|
|
{
|
|
|
|
int CC_id;
|
|
|
|
// Framing variables
|
|
int32_t sf;
|
|
|
|
char fname[64], vname[64];
|
|
|
|
//#ifdef XFORMS
|
|
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
|
|
// at eNB 0, an UL scope for every UE
|
|
FD_lte_phy_scope_ue *form_ue[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
|
|
FD_lte_phy_scope_enb *form_enb[NUMBER_OF_UE_MAX];
|
|
char title[255];
|
|
char xname[32] = "oaisim";
|
|
int xargc = 1;
|
|
char *xargv[1];
|
|
//#endif
|
|
|
|
#undef PRINT_STATS /* this undef is to avoid gcc warnings */
|
|
#define PRINT_STATS
|
|
#ifdef PRINT_STATS
|
|
int len;
|
|
FILE *UE_stats[NUMBER_OF_UE_MAX];
|
|
FILE *UE_stats_th[NUMBER_OF_UE_MAX];
|
|
FILE *eNB_stats[NUMBER_OF_eNB_MAX];
|
|
FILE *eNB_avg_thr;
|
|
FILE *eNB_l2_stats;
|
|
char UE_stats_filename[255];
|
|
char eNB_stats_filename[255];
|
|
char UE_stats_th_filename[255];
|
|
char eNB_stats_th_filename[255];
|
|
#endif
|
|
|
|
|
|
if (xforms==1) {
|
|
xargv[0] = xname;
|
|
fl_initialize (&xargc, xargv, NULL, 0, 0);
|
|
eNB_inst = 0;
|
|
for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
|
|
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
|
|
// DL scope at UEs
|
|
form_ue[CC_id][UE_inst] = create_lte_phy_scope_ue();
|
|
sprintf (title, "LTE DL SCOPE eNB %d to UE %d CC_id %d", eNB_inst, UE_inst, CC_id);
|
|
fl_show_form (form_ue[CC_id][UE_inst]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
|
|
|
|
if (PHY_vars_UE_g[UE_inst][CC_id]->use_ia_receiver == 1) {
|
|
fl_set_button(form_ue[CC_id][UE_inst]->button_0,1);
|
|
fl_set_object_label(form_ue[CC_id][UE_inst]->button_0, "IA Receiver ON");
|
|
fl_set_object_color(form_ue[CC_id][UE_inst]->button_0, FL_GREEN, FL_GREEN);
|
|
}
|
|
|
|
}
|
|
// UL scope at eNB 0
|
|
form_enb[UE_inst] = create_lte_phy_scope_enb();
|
|
sprintf (title, "LTE UL SCOPE UE %d to eNB %d", UE_inst, eNB_inst);
|
|
fl_show_form (form_enb[UE_inst]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef PRINT_STATS
|
|
|
|
for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
|
|
sprintf(UE_stats_filename,"UE_stats%d.txt",UE_inst);
|
|
UE_stats[UE_inst] = fopen (UE_stats_filename, "w");
|
|
}
|
|
|
|
for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
|
|
sprintf(eNB_stats_filename,"eNB_stats%d.txt",eNB_inst);
|
|
eNB_stats[eNB_inst] = fopen (eNB_stats_filename, "w");
|
|
}
|
|
|
|
if(abstraction_flag==0) {
|
|
for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
|
|
/* TODO: transmission_mode is defined per CC, we set 0 for now */
|
|
sprintf(UE_stats_th_filename,"UE_stats_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
|
|
UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
|
|
}
|
|
|
|
/* TODO: transmission_mode is defined per CC, we set 0 for now */
|
|
sprintf(eNB_stats_th_filename,"eNB_stats_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
|
|
eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
|
|
} else {
|
|
for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
|
|
/* TODO: transmission_mode is defined per CC, we set 0 for now */
|
|
sprintf(UE_stats_th_filename,"UE_stats_abs_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
|
|
UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
|
|
}
|
|
|
|
/* TODO: transmission_mode is defined per CC, we set 0 for now */
|
|
sprintf(eNB_stats_th_filename,"eNB_stats_abs_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
|
|
eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
|
|
}
|
|
|
|
#ifdef OPENAIR2
|
|
eNB_l2_stats = fopen ("eNB_l2_stats.txt", "w");
|
|
LOG_I(EMU,"eNB_l2_stats=%p\n", eNB_l2_stats);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
MessageDef *message_p = NULL;
|
|
const char *msg_name = NULL;
|
|
int result;
|
|
|
|
itti_mark_task_ready (TASK_L2L1);
|
|
LOG_I(EMU, "TASK_L2L1 is READY\n");
|
|
|
|
if (oai_emulation.info.nb_enb_local > 0) {
|
|
/* Wait for the initialize message */
|
|
do {
|
|
if (message_p != NULL) {
|
|
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
|
}
|
|
|
|
itti_receive_msg (TASK_L2L1, &message_p);
|
|
msg_name = ITTI_MSG_NAME (message_p);
|
|
LOG_I(EMU, "TASK_L2L1 received %s in state L2L1_WAITTING\n", msg_name);
|
|
|
|
switch (ITTI_MSG_ID(message_p)) {
|
|
case INITIALIZE_MESSAGE:
|
|
l2l1_state = L2L1_RUNNING;
|
|
break;
|
|
|
|
case ACTIVATE_MESSAGE:
|
|
set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
|
|
break;
|
|
|
|
case DEACTIVATE_MESSAGE:
|
|
set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
|
|
break;
|
|
|
|
case TERMINATE_MESSAGE:
|
|
l2l1_state = L2L1_TERMINATED;
|
|
break;
|
|
|
|
default:
|
|
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
|
|
break;
|
|
}
|
|
} while (l2l1_state == L2L1_WAITTING);
|
|
|
|
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
|
}
|
|
|
|
#endif
|
|
module_id_t enb_id;
|
|
module_id_t UE_id;
|
|
for (enb_id = 0; enb_id < NB_eNB_INST; enb_id++)
|
|
mac_xface->mrbch_phy_sync_failure (enb_id, 0, enb_id);
|
|
|
|
if (abstraction_flag == 1) {
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++)
|
|
mac_xface->dl_phy_sync_success (UE_id, 0, 0,1); //UE_id%NB_eNB_INST);
|
|
}
|
|
|
|
start_meas (&oaisim_stats);
|
|
|
|
for (frame = 0;
|
|
(l2l1_state != L2L1_TERMINATED) &&
|
|
((oai_emulation.info.n_frames_flag == 0) ||
|
|
(frame < oai_emulation.info.n_frames));
|
|
frame++) {
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
|
|
do {
|
|
// Checks if a message has been sent to L2L1 task
|
|
itti_poll_msg (TASK_L2L1, &message_p);
|
|
|
|
if (message_p != NULL) {
|
|
msg_name = ITTI_MSG_NAME (message_p);
|
|
LOG_I(EMU, "TASK_L2L1 received %s\n", msg_name);
|
|
|
|
switch (ITTI_MSG_ID(message_p)) {
|
|
case ACTIVATE_MESSAGE:
|
|
set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
|
|
break;
|
|
|
|
case DEACTIVATE_MESSAGE:
|
|
set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
|
|
break;
|
|
|
|
case TERMINATE_MESSAGE:
|
|
l2l1_state = L2L1_TERMINATED;
|
|
break;
|
|
|
|
case MESSAGE_TEST:
|
|
break;
|
|
|
|
default:
|
|
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
|
|
break;
|
|
}
|
|
|
|
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
|
}
|
|
} while(message_p != NULL);
|
|
|
|
#endif
|
|
|
|
//Run the aperiodic user-defined events
|
|
if (oai_emulation.info.oeh_enabled == 1)
|
|
execute_events (frame);
|
|
|
|
if (ue_connection_test == 1) {
|
|
if ((frame % 20) == 0) {
|
|
snr_dB += snr_direction;
|
|
sinr_dB -= snr_direction;
|
|
}
|
|
|
|
if (snr_dB == -20) {
|
|
snr_direction = snr_step;
|
|
} else if (snr_dB == 20) {
|
|
snr_direction = -snr_step;
|
|
}
|
|
}
|
|
|
|
oai_emulation.info.frame = frame;
|
|
//oai_emulation.info.time_ms += 1;
|
|
oai_emulation.info.time_s += 0.01; // emu time in s, each frame lasts for 10 ms // JNote: TODO check the coherency of the time and frame (I corrected it to 10 (instead of 0.01)
|
|
|
|
update_omg (frame); // frequency is defined in the omg_global params configurable by the user
|
|
update_omg_ocm ();
|
|
|
|
#ifdef OPENAIR2
|
|
|
|
// check if pipe is still open
|
|
if ((oai_emulation.info.omv_enabled == 1)) {
|
|
omv_write (pfd[1], enb_node_list, ue_node_list, omv_data);
|
|
}
|
|
|
|
#endif
|
|
|
|
update_ocm ();
|
|
|
|
for (sf = 0; sf < 10; sf++) {
|
|
start_meas (&oaisim_stats_f);
|
|
|
|
wait_for_slot_isr ();
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
itti_update_lte_time(frame % MAX_FRAME_NUMBER, sf<<1);
|
|
#endif
|
|
|
|
oai_emulation.info.time_ms = frame * 10 + sf;
|
|
|
|
#ifdef PROC
|
|
|
|
if(Channel_Flag==1)
|
|
Channel_Func(s_re2,s_im2,r_re2,r_im2,r_re02,r_im02,r_re0_d,r_im0_d,r_re0_u,r_im0_u,eNB2UE,UE2eNB,enb_data,ue_data,abstraction_flag,frame_parms,sf<<1);
|
|
|
|
if(Channel_Flag==0)
|
|
#endif
|
|
{ // SUBFRAME INNER PART
|
|
#if defined(ENABLE_ITTI)
|
|
log_set_instance_type (LOG_INSTANCE_ENB);
|
|
#endif
|
|
|
|
clear_eNB_transport_info (oai_emulation.info.nb_enb_local);
|
|
|
|
CC_id=0;
|
|
int all_done=0;
|
|
while (all_done==0) {
|
|
pthread_mutex_lock(&subframe_mutex);
|
|
int subframe_eNB_mask_local = subframe_eNB_mask;
|
|
int subframe_UE_mask_local = subframe_UE_mask;
|
|
pthread_mutex_unlock(&subframe_mutex);
|
|
LOG_D(EMU,"Frame %d, Subframe %d: Checking masks %x,%x\n",frame,sf,subframe_eNB_mask,subframe_UE_mask);
|
|
if ((subframe_eNB_mask_local == ((1<<NB_eNB_INST)-1)) &&
|
|
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1)))
|
|
all_done=1;
|
|
else
|
|
usleep(500);
|
|
}
|
|
|
|
//clear subframe masks for next round
|
|
pthread_mutex_lock(&subframe_mutex);
|
|
subframe_eNB_mask=0;
|
|
subframe_UE_mask=0;
|
|
pthread_mutex_unlock(&subframe_mutex);
|
|
|
|
// increment timestamps
|
|
for (eNB_inst = oai_emulation.info.first_enb_local;
|
|
(eNB_inst
|
|
< (oai_emulation.info.first_enb_local
|
|
+ oai_emulation.info.nb_enb_local));
|
|
eNB_inst++) {
|
|
|
|
current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
|
|
}
|
|
for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
|
|
current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
|
}
|
|
|
|
|
|
if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) {
|
|
T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(slot/2));
|
|
/*
|
|
LOG_D(EMU,
|
|
"PHY procedures eNB %d for frame %d, slot %d (subframe TX %d, RX %d) TDD %d/%d Nid_cell %d\n",
|
|
eNB_inst,
|
|
frame%MAX_FRAME_NUMBER,
|
|
2*sf,
|
|
PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_tx,
|
|
PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_rx,
|
|
PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.frame_type,
|
|
PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.tdd_config,
|
|
PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.Nid_cell);
|
|
*/
|
|
}
|
|
|
|
for (eNB_inst = oai_emulation.info.first_enb_local;
|
|
(eNB_inst
|
|
< (oai_emulation.info.first_enb_local
|
|
+ oai_emulation.info.nb_enb_local));
|
|
eNB_inst++) {
|
|
if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) {
|
|
|
|
T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(sf));
|
|
/*
|
|
LOG_D(EMU,
|
|
"PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n",
|
|
eNB_inst,
|
|
frame % MAX_FRAME_NUMBER,
|
|
sf,
|
|
PHY_vars_eNB_g[eNB_inst][0]->frame_parms.frame_type,
|
|
PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config,
|
|
PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell);
|
|
|
|
*/
|
|
#ifdef OPENAIR2
|
|
//Application: traffic gen
|
|
update_otg_eNB (eNB_inst, oai_emulation.info.time_ms);
|
|
|
|
//IP/OTG to PDCP and PDCP to IP operation
|
|
// pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id
|
|
#endif
|
|
|
|
|
|
#ifdef PRINT_STATS
|
|
|
|
if((sf==9) && frame%10==0)
|
|
if(eNB_avg_thr)
|
|
fprintf(eNB_avg_thr,"%d %d\n",PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx,
|
|
(PHY_vars_eNB_g[eNB_inst][0]->total_system_throughput)/((PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx+1)*10));
|
|
|
|
if (eNB_stats[eNB_inst]) {
|
|
len = dump_eNB_stats(PHY_vars_eNB_g[eNB_inst][0], stats_buffer, 0);
|
|
rewind (eNB_stats[eNB_inst]);
|
|
fwrite (stats_buffer, 1, len, eNB_stats[eNB_inst]);
|
|
fflush(eNB_stats[eNB_inst]);
|
|
}
|
|
|
|
#ifdef OPENAIR2
|
|
|
|
if (eNB_l2_stats) {
|
|
len = dump_eNB_l2_stats (stats_buffer, 0);
|
|
rewind (eNB_l2_stats);
|
|
fwrite (stats_buffer, 1, len, eNB_l2_stats);
|
|
fflush(eNB_l2_stats);
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
}
|
|
}// eNB_inst loop
|
|
|
|
// Call ETHERNET emulation here
|
|
//emu_transport (frame, last_slot, next_slot, direction, oai_emulation.info.frame_type, ethernet_flag);
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
log_set_instance_type (LOG_INSTANCE_UE);
|
|
#endif
|
|
|
|
|
|
/*
|
|
clear_UE_transport_info (oai_emulation.info.nb_ue_local);
|
|
clear_UE_transport_info (oai_emulation.info.nb_ue_local);
|
|
|
|
for (UE_inst = oai_emulation.info.first_ue_local;
|
|
(UE_inst < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local));
|
|
UE_inst++) {
|
|
if (oai_emulation.info.cli_start_ue[UE_inst] != 0) {
|
|
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
|
|
|
|
#else
|
|
|
|
if (frame >= (UE_inst * 20)) // activate UE only after 20*UE_id frames so that different UEs turn on separately
|
|
#endif
|
|
{
|
|
LOG_D(EMU,
|
|
"PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n",
|
|
UE_inst, frame % MAX_FRAME_NUMBER, slot, next_slot >> 1,
|
|
last_slot >> 1);
|
|
|
|
if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0]
|
|
!= NOT_SYNCHED) {
|
|
if (frame > 0) {
|
|
PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER;
|
|
PHY_vars_UE_g[UE_inst][0]->slot_rx = last_slot;
|
|
PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot;
|
|
|
|
if (next_slot > 1)
|
|
PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER;
|
|
else
|
|
PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame + 1) % MAX_FRAME_NUMBER;
|
|
#ifdef OPENAIR2
|
|
//Application
|
|
update_otg_UE (UE_inst, oai_emulation.info.time_ms);
|
|
|
|
//Access layer
|
|
// PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, ENB_FLAG_NO, NOT_A_RNTI, frame, next_slot>>1, 0);
|
|
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, next_slot);
|
|
pdcp_run (&ctxt);
|
|
#endif
|
|
|
|
for (CC_id = 0; CC_id < MAX_NUM_CCs;
|
|
CC_id++) {
|
|
phy_procedures_UE_lte (
|
|
PHY_vars_UE_g[UE_inst][CC_id],
|
|
0, abstraction_flag,
|
|
normal_txrx, no_relay,
|
|
NULL);
|
|
}
|
|
|
|
ue_data[UE_inst]->tx_power_dBm =
|
|
PHY_vars_UE_g[UE_inst][0]->tx_power_dBm;
|
|
}
|
|
} else {
|
|
if (abstraction_flag == 1) {
|
|
LOG_E(EMU,
|
|
"sync not supported in abstraction mode (UE%d,mode%d)\n",
|
|
UE_inst,
|
|
PHY_vars_UE_g[UE_inst][0]->UE_mode[0]);
|
|
exit (-1);
|
|
}
|
|
|
|
if ((frame > 0)
|
|
&& (last_slot
|
|
== (LTE_SLOTS_PER_FRAME
|
|
- 2))) {
|
|
initial_sync (PHY_vars_UE_g[UE_inst][0],
|
|
normal_txrx);
|
|
|
|
}
|
|
}
|
|
|
|
#ifdef PRINT_STATS
|
|
|
|
if(last_slot==2 && frame%10==0) {
|
|
if (UE_stats_th[UE_inst]) {
|
|
fprintf(UE_stats_th[UE_inst],"%d %d\n",frame%MAX_FRAME_NUMBER, PHY_vars_UE_g[UE_inst][0]->bitrate[0]/1000);
|
|
}
|
|
}
|
|
|
|
if (UE_stats[UE_inst]) {
|
|
len = dump_ue_stats (PHY_vars_UE_g[UE_inst][0], stats_buffer, 0, normal_txrx, 0);
|
|
rewind (UE_stats[UE_inst]);
|
|
fwrite (stats_buffer, 1, len, UE_stats[UE_inst]);
|
|
fflush(UE_stats[UE_inst]);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef Rel10
|
|
|
|
for (RN_id=oai_emulation.info.first_rn_local;
|
|
RN_id<oai_emulation.info.first_rn_local+oai_emulation.info.nb_rn_local;
|
|
RN_id++) {
|
|
// UE id and eNB id of the RN
|
|
UE_inst= oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local + RN_id;// NB_UE_INST + RN_id
|
|
eNB_inst= oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local + RN_id;// NB_eNB_INST + RN_id
|
|
|
|
// currently only works in FDD
|
|
if (oai_emulation.info.eMBMS_active_state == 4) {
|
|
r_type = multicast_relay;
|
|
//LOG_I(EMU,"Activating the multicast relaying\n");
|
|
} else {
|
|
LOG_E(EMU,"Not supported eMBMS option when relaying is enabled %d\n", r_type);
|
|
exit(-1);
|
|
}
|
|
|
|
PHY_vars_RN_g[RN_id]->frame = frame % MAX_FRAME_NUMBER;
|
|
|
|
if ( oai_emulation.info.frame_type == 0) {
|
|
// RN == UE
|
|
if (frame>0) {
|
|
if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] != NOT_SYNCHED) {
|
|
LOG_D(EMU,"[RN %d] PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n",
|
|
RN_id, UE_inst, frame, slot, next_slot >> 1,last_slot>>1);
|
|
PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER;
|
|
PHY_vars_UE_g[UE_inst][0]->slot_rx = last_slot;
|
|
PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot;
|
|
|
|
if (next_slot>1) PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER;
|
|
else PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame+1) % MAX_FRAME_NUMBER;
|
|
|
|
phy_procedures_UE_lte (PHY_vars_UE_g[UE_inst][0], 0, abstraction_flag,normal_txrx,
|
|
r_type, PHY_vars_RN_g[RN_id]);
|
|
} else if (last_slot == (LTE_SLOTS_PER_FRAME-2)) {
|
|
initial_sync(PHY_vars_UE_g[UE_inst][0],normal_txrx);
|
|
}
|
|
}
|
|
|
|
emu_transport (frame % MAX_FRAME_NUMBER, sf<<1, ((sf+4)%10)<<1, subframe_select(&PHY_vars_eNB_g[0][0]->frame_parms,sf),
|
|
oai_emulation.info.frame_type[0], ethernet_flag);
|
|
|
|
start_meas (&dl_chan_stats);
|
|
|
|
for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++)
|
|
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
|
//#warning figure out what to do with UE frame_parms during initial_sync
|
|
do_DL_sig (r_re0,
|
|
r_im0,
|
|
r_re,
|
|
r_im,
|
|
s_re,
|
|
s_im,
|
|
eNB2UE,
|
|
enb_data,
|
|
ue_data,
|
|
PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1,
|
|
abstraction_flag,
|
|
&PHY_vars_eNB_g[0][CC_id]->frame_parms,
|
|
UE_inst, CC_id);
|
|
do_DL_sig (r_re0,
|
|
r_im0,
|
|
r_re,
|
|
r_im,
|
|
s_re,
|
|
s_im,
|
|
eNB2UE,
|
|
enb_data,
|
|
ue_data,
|
|
(PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1,
|
|
abstraction_flag,
|
|
&PHY_vars_eNB_g[0][CC_id]->frame_parms,
|
|
UE_inst, CC_id);
|
|
}
|
|
|
|
stop_meas (&dl_chan_stats);
|
|
|
|
|
|
start_meas (&ul_chan_stats);
|
|
|
|
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
|
//#warning figure out what to do with UE frame_parms during initial_sync
|
|
do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB,
|
|
enb_data, ue_data,
|
|
PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1,
|
|
abstraction_flag,
|
|
&PHY_vars_eNB_g[0][CC_id]->frame_parms,
|
|
frame % MAX_FRAME_NUMBER, CC_id);
|
|
do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB,
|
|
enb_data, ue_data,
|
|
(PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1,
|
|
abstraction_flag,
|
|
&PHY_vars_eNB_g[0][CC_id]->frame_parms,
|
|
frame % MAX_FRAME_NUMBER, CC_id);
|
|
}
|
|
|
|
stop_meas (&ul_chan_stats);
|
|
|
|
*/
|
|
|
|
if ((sf == 0) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0)
|
|
&& (oai_emulation.info.n_frames == 1)) {
|
|
|
|
write_output ("dlchan0.m",
|
|
"dlch0",
|
|
&(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[0][0][0]),
|
|
(6
|
|
* (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
|
|
1, 1);
|
|
write_output ("dlchan1.m",
|
|
"dlch1",
|
|
&(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[1][0][0]),
|
|
(6
|
|
* (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
|
|
1, 1);
|
|
write_output ("dlchan2.m",
|
|
"dlch2",
|
|
&(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[2][0][0]),
|
|
(6
|
|
* (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
|
|
1, 1);
|
|
write_output ("pbch_rxF_comp0.m",
|
|
"pbch_comp0",
|
|
PHY_vars_UE_g[0][0]->pbch_vars[0]->rxdataF_comp[0],
|
|
6 * 12 * 4, 1, 1);
|
|
write_output ("pbch_rxF_llr.m", "pbch_llr",
|
|
PHY_vars_UE_g[0][0]->pbch_vars[0]->llr,
|
|
(frame_parms[0]->Ncp == 0) ? 1920 : 1728, 1,
|
|
4);
|
|
}
|
|
|
|
stop_meas (&oaisim_stats_f);
|
|
} // SUBFRAME INNER PART
|
|
|
|
|
|
}
|
|
|
|
if ((frame >= 10) && (frame <= 11) && (abstraction_flag == 0)
|
|
#ifdef PROC
|
|
&&(Channel_Flag==0)
|
|
#endif
|
|
) {
|
|
sprintf (fname, "UEtxsig%d.m", frame % MAX_FRAME_NUMBER);
|
|
sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
|
|
write_output (fname,
|
|
vname,
|
|
PHY_vars_UE_g[0][0]->common_vars.txdata[0],
|
|
PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
|
|
* 10,
|
|
1, 1);
|
|
sprintf (fname, "eNBtxsig%d.m", frame % MAX_FRAME_NUMBER);
|
|
sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
|
|
write_output (fname,
|
|
vname,
|
|
PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0],
|
|
PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
|
|
* 10,
|
|
1, 1);
|
|
sprintf (fname, "eNBtxsigF%d.m", frame % MAX_FRAME_NUMBER);
|
|
sprintf (vname, "txsF%d", frame % MAX_FRAME_NUMBER);
|
|
write_output (fname,
|
|
vname,
|
|
PHY_vars_eNB_g[0][0]->common_vars.txdataF[0][0],
|
|
PHY_vars_eNB_g[0][0]->frame_parms.symbols_per_tti
|
|
* PHY_vars_eNB_g[0][0]->frame_parms.ofdm_symbol_size,
|
|
1, 1);
|
|
sprintf (fname, "UErxsig%d.m", frame % MAX_FRAME_NUMBER);
|
|
sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
|
|
write_output (fname,
|
|
vname,
|
|
PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
|
|
PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
|
|
* 10,
|
|
1, 1);
|
|
sprintf (fname, "eNBrxsig%d.m", frame % MAX_FRAME_NUMBER);
|
|
sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
|
|
write_output (fname,
|
|
vname,
|
|
PHY_vars_eNB_g[0][0]->common_vars.rxdata[0][0],
|
|
PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
|
|
* 10,
|
|
1, 1);
|
|
}
|
|
|
|
//#ifdef XFORMS
|
|
if (xforms==1) {
|
|
eNB_inst = 0;
|
|
|
|
for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
|
|
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
|
|
phy_scope_UE(form_ue[CC_id][UE_inst],
|
|
PHY_vars_UE_g[UE_inst][CC_id],
|
|
eNB_inst,
|
|
UE_inst,
|
|
7);
|
|
}
|
|
|
|
phy_scope_eNB(form_enb[UE_inst],
|
|
PHY_vars_eNB_g[eNB_inst][0],
|
|
UE_inst);
|
|
|
|
}
|
|
}
|
|
//#endif
|
|
|
|
#ifdef SMBV
|
|
|
|
// Rohde&Schwarz SMBV100A vector signal generator
|
|
if ((frame % MAX_FRAME_NUMBER == config_frames[0]) || (frame % MAX_FRAME_NUMBER == config_frames[1]) || (frame % MAX_FRAME_NUMBER == config_frames[2]) || (frame % MAX_FRAME_NUMBER == config_frames[3])) {
|
|
smbv_frame_cnt++;
|
|
}
|
|
|
|
#endif
|
|
|
|
} // frame loop
|
|
|
|
stop_meas (&oaisim_stats);
|
|
oai_shutdown ();
|
|
|
|
#ifdef PRINT_STATS
|
|
|
|
for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
|
|
if (UE_stats[UE_inst])
|
|
fclose (UE_stats[UE_inst]);
|
|
|
|
if(UE_stats_th[UE_inst])
|
|
fclose (UE_stats_th[UE_inst]);
|
|
}
|
|
|
|
for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
|
|
if (eNB_stats[eNB_inst])
|
|
fclose (eNB_stats[eNB_inst]);
|
|
}
|
|
|
|
if (eNB_avg_thr)
|
|
fclose (eNB_avg_thr);
|
|
|
|
if (eNB_l2_stats)
|
|
fclose (eNB_l2_stats);
|
|
|
|
#endif
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
itti_terminate_tasks(TASK_L2L1);
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#if T_TRACER
|
|
int T_wait = 1; /* by default we wait for the tracer */
|
|
int T_port = 2021; /* default port to listen to to wait for the tracer */
|
|
int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
|
|
clock_t t;
|
|
|
|
#ifdef SMBV
|
|
// Rohde&Schwarz SMBV100A vector signal generator
|
|
strcpy(smbv_ip,DEFAULT_SMBV_IP);
|
|
#endif
|
|
|
|
#ifdef PROC
|
|
int node_id;
|
|
int port,Process_Flag=0,wgt,Channel_Flag=0,temp;
|
|
#endif
|
|
|
|
//default parameters
|
|
oai_emulation.info.n_frames = MAX_FRAME_NUMBER; //1024; //10;
|
|
oai_emulation.info.n_frames_flag = 0; //fixme
|
|
snr_dB = 30;
|
|
|
|
//Default values if not changed by the user in get_simulation_options();
|
|
pdcp_period = 1;
|
|
omg_period = 1;
|
|
// start thread for log gen
|
|
log_thread_init ();
|
|
|
|
init_oai_emulation (); // to initialize everything !!!
|
|
|
|
// get command-line options
|
|
get_simulation_options (argc, argv); //Command-line options
|
|
|
|
#if T_TRACER
|
|
T_init(T_port, T_wait, T_dont_fork);
|
|
#endif
|
|
|
|
// Initialize VCD LOG module
|
|
VCD_SIGNAL_DUMPER_INIT (oai_emulation.info.vcd_file);
|
|
|
|
#if !defined(ENABLE_ITTI)
|
|
pthread_t tid;
|
|
int err;
|
|
sigset_t sigblock;
|
|
sigemptyset (&sigblock);
|
|
sigaddset (&sigblock, SIGHUP);
|
|
sigaddset (&sigblock, SIGINT);
|
|
sigaddset (&sigblock, SIGTERM);
|
|
sigaddset (&sigblock, SIGQUIT);
|
|
//sigaddset(&sigblock, SIGKILL);
|
|
|
|
if ((err = pthread_sigmask (SIG_BLOCK, &sigblock, NULL)) != 0) {
|
|
printf ("SIG_BLOCK error\n");
|
|
return -1;
|
|
}
|
|
|
|
if (pthread_create (&tid, NULL, sigh, NULL)) {
|
|
printf ("Pthread for tracing Signals is not created!\n");
|
|
return -1;
|
|
} else {
|
|
printf ("Pthread for tracing Signals is created!\n");
|
|
}
|
|
|
|
#endif
|
|
// configure oaisim with OCG
|
|
oaisim_config (); // config OMG and OCG, OPT, OTG, OLG
|
|
|
|
if (ue_connection_test == 1) {
|
|
snr_direction = -snr_step;
|
|
snr_dB = 20;
|
|
sinr_dB = -20;
|
|
}
|
|
|
|
pthread_cond_init(&sync_cond,NULL);
|
|
pthread_mutex_init(&sync_mutex, NULL);
|
|
pthread_mutex_init(&subframe_mutex, NULL);
|
|
|
|
#ifdef OPENAIR2
|
|
init_omv ();
|
|
#endif
|
|
//Before this call, NB_UE_INST and NB_eNB_INST are not set correctly
|
|
check_and_adjust_params ();
|
|
|
|
set_seed = oai_emulation.emulation_config.seed.value;
|
|
|
|
init_otg_pdcp_buffer ();
|
|
|
|
init_seed (set_seed);
|
|
|
|
init_openair1 ();
|
|
|
|
init_openair2 ();
|
|
|
|
init_ocm ();
|
|
|
|
// wait for all threads to startup
|
|
sleep(3);
|
|
printf("Sending sync to all threads\n");
|
|
|
|
pthread_mutex_lock(&sync_mutex);
|
|
sync_var=0;
|
|
pthread_cond_broadcast(&sync_cond);
|
|
pthread_mutex_unlock(&sync_mutex);
|
|
|
|
#ifdef SMBV
|
|
// Rohde&Schwarz SMBV100A vector signal generator
|
|
smbv_init_config(smbv_fname, smbv_nframes);
|
|
smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->frame_parms);
|
|
#endif
|
|
|
|
/* #if defined (FLEXRAN_AGENT_SB_IF)
|
|
flexran_agent_start();
|
|
#endif */
|
|
|
|
// add events to future event list: Currently not used
|
|
//oai_emulation.info.oeh_enabled = 1;
|
|
if (oai_emulation.info.oeh_enabled == 1)
|
|
schedule_events ();
|
|
|
|
// oai performance profiler is enabled
|
|
if (oai_emulation.info.opp_enabled == 1)
|
|
reset_opp_meas_oaisim ();
|
|
|
|
init_time ();
|
|
|
|
init_slot_isr ();
|
|
|
|
t = clock ();
|
|
|
|
LOG_N(EMU,
|
|
">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
|
|
// Handle signals until all tasks are terminated
|
|
if (create_tasks(oai_emulation.info.nb_enb_local, oai_emulation.info.nb_ue_local) >= 0) {
|
|
itti_wait_tasks_end();
|
|
} else {
|
|
exit(-1); // need a softer mode
|
|
}
|
|
|
|
#else
|
|
|
|
if (oai_emulation.info.nb_enb_local > 0) {
|
|
eNB_app_task (NULL); // do nothing for the moment
|
|
}
|
|
|
|
l2l1_task (NULL);
|
|
#endif
|
|
t = clock () - t;
|
|
LOG_I(EMU, "Duration of the simulation: %f seconds\n",
|
|
((float) t) / CLOCKS_PER_SEC);
|
|
|
|
LOG_N(EMU,
|
|
">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU Ending <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
|
|
|
|
raise (SIGINT);
|
|
// oai_shutdown ();
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
reset_opp_meas_oaisim (void)
|
|
{
|
|
uint8_t eNB_id = 0, UE_id = 0;
|
|
|
|
reset_meas (&oaisim_stats);
|
|
reset_meas (&oaisim_stats_f); // frame
|
|
|
|
// init time stats here (including channel)
|
|
reset_meas (&dl_chan_stats);
|
|
reset_meas (&ul_chan_stats);
|
|
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx);
|
|
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats);
|
|
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats);
|
|
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->tx_prach);
|
|
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats);
|
|
reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats);
|
|
/*
|
|
* L2 functions
|
|
*/
|
|
|
|
// UE MAC
|
|
reset_meas (&UE_mac_inst[UE_id].ue_scheduler); // total
|
|
reset_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu); // inlcude rlc_data_req + mac header gen
|
|
reset_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu); // include mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind and mac header parser
|
|
reset_meas (&UE_mac_inst[UE_id].ue_query_mch);
|
|
reset_meas (&UE_mac_inst[UE_id].rx_mch_sdu); // include rld_data_ind+ parse mch header
|
|
reset_meas (&UE_mac_inst[UE_id].rx_si); // include rlc_data_ind + mac header parser
|
|
|
|
reset_meas (&UE_pdcp_stats[UE_id].pdcp_run);
|
|
reset_meas (&UE_pdcp_stats[UE_id].data_req);
|
|
reset_meas (&UE_pdcp_stats[UE_id].data_ind);
|
|
reset_meas (&UE_pdcp_stats[UE_id].apply_security);
|
|
reset_meas (&UE_pdcp_stats[UE_id].validate_security);
|
|
reset_meas (&UE_pdcp_stats[UE_id].pdcp_ip);
|
|
reset_meas (&UE_pdcp_stats[UE_id].ip_pdcp);
|
|
|
|
}
|
|
|
|
for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
|
|
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
|
reset_meas (&eNB2UE[eNB_id][UE_id][0]->random_channel);
|
|
reset_meas (&eNB2UE[eNB_id][UE_id][0]->interp_time);
|
|
reset_meas (&eNB2UE[eNB_id][UE_id][0]->interp_freq);
|
|
reset_meas (&eNB2UE[eNB_id][UE_id][0]->convolution);
|
|
reset_meas (&UE2eNB[UE_id][eNB_id][0]->random_channel);
|
|
reset_meas (&UE2eNB[UE_id][eNB_id][0]->interp_time);
|
|
reset_meas (&UE2eNB[UE_id][eNB_id][0]->interp_freq);
|
|
reset_meas (&UE2eNB[UE_id][eNB_id][0]->convolution);
|
|
}
|
|
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_rx);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_tx);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->rx_prach);
|
|
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_mod_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_encoding_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_modulation_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_scrambling_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_rate_matching_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_turbo_encoding_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_interleaving_stats);
|
|
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_demod_stats);
|
|
//reset_meas(&PHY_vars_eNB_g[eNB_id]->rx_dft_stats);
|
|
//reset_meas(&PHY_vars_eNB_g[eNB_id]->ulsch_channel_estimation_stats);
|
|
//reset_meas(&PHY_vars_eNB_g[eNB_id]->ulsch_freq_offset_estimation_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_decoding_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demodulation_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_rate_unmatching_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_turbo_decoding_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_deinterleaving_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demultiplexing_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_llr_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_init_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_alpha_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_beta_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_gamma_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_ext_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl1_stats);
|
|
reset_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl2_stats);
|
|
#ifdef LOCALIZATION
|
|
reset_meas(&PHY_vars_eNB_g[eNB_id][0]->localization_stats);
|
|
#endif
|
|
|
|
/*
|
|
* L2 functions
|
|
*/
|
|
// eNB MAC
|
|
reset_meas (&eNB_mac_inst[eNB_id].eNB_scheduler); // total
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_si); // only schedule + tx
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_ra); // only ra
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_ulsch); // onlu ulsch
|
|
reset_meas (&eNB_mac_inst[eNB_id].fill_DLSCH_dci); // only dci
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_dlsch_preprocessor); // include rlc_data_req + MAC header gen
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_dlsch); // include rlc_data_req + MAC header gen + pre-processor
|
|
reset_meas (&eNB_mac_inst[eNB_id].schedule_mch); // only embms
|
|
reset_meas (&eNB_mac_inst[eNB_id].rx_ulsch_sdu); // include rlc_data_ind + mac header parser
|
|
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_run);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].data_req);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].data_ind);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].apply_security);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].validate_security);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip);
|
|
reset_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
print_opp_meas_oaisim (void)
|
|
{
|
|
|
|
uint8_t eNB_id = 0, UE_id = 0;
|
|
|
|
print_meas (&oaisim_stats, "[OAI][total_exec_time]", &oaisim_stats,
|
|
&oaisim_stats);
|
|
print_meas (&oaisim_stats_f, "[OAI][SF_exec_time]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
|
|
print_meas (&dl_chan_stats, "[DL][chan_stats]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
print_meas (&ul_chan_stats, "[UL][chan_stats]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
|
for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
|
|
print_meas (&eNB2UE[eNB_id][UE_id][0]->random_channel,
|
|
"[DL][random_channel]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB2UE[eNB_id][UE_id][0]->interp_time,
|
|
"[DL][interp_time]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB2UE[eNB_id][UE_id][0]->interp_freq,
|
|
"[DL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB2UE[eNB_id][UE_id][0]->convolution,
|
|
"[DL][convolution]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&UE2eNB[UE_id][eNB_id][0]->random_channel,
|
|
"[UL][random_channel]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE2eNB[UE_id][eNB_id][0]->interp_time,
|
|
"[UL][interp_time]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE2eNB[UE_id][eNB_id][0]->interp_freq,
|
|
"[UL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE2eNB[UE_id][eNB_id][0]->convolution,
|
|
"[UL][convolution]", &oaisim_stats, &oaisim_stats_f);
|
|
}
|
|
}
|
|
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc, "[UE][total_phy_proc]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx,
|
|
"[UE][total_phy_proc_rx]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats,
|
|
"[UE][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats, "[UE][rx_dft]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats,
|
|
"[UE][channel_est]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats,
|
|
"[UE][freq_offset]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats, "[UE][llr]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats,
|
|
"[UE][unscrambling]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats,
|
|
"[UE][decoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats,
|
|
"[UE][rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats,
|
|
"[UE][deinterleaving]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats,
|
|
"[UE][turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats,
|
|
"[UE][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats,
|
|
"[UE][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats,
|
|
"[UE][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats,
|
|
"[UE][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats,
|
|
"[UE][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats,
|
|
"[UE][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats,
|
|
"[UE][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx,
|
|
"[UE][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats, "[UE][ofdm_mod]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats,
|
|
"[UE][modulation]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats,
|
|
"[UE][encoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats,
|
|
"[UE][segmentation]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats,
|
|
"[UE][rate_matching]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats,
|
|
"[UE][turbo_encoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats,
|
|
"[UE][interleaving]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats,
|
|
"[UE][multiplexing]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
}
|
|
|
|
for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc,
|
|
"[eNB][total_phy_proc]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_tx,
|
|
"[eNB][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_mod_stats,
|
|
"[eNB][ofdm_mod]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_modulation_stats,
|
|
"[eNB][modulation]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_scrambling_stats,
|
|
"[eNB][scrambling]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_encoding_stats,
|
|
"[eNB][encoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_interleaving_stats,
|
|
"[eNB][|_interleaving]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_rate_matching_stats,
|
|
"[eNB][|_rate_matching]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->dlsch_turbo_encoding_stats,
|
|
"[eNB][|_turbo_encoding]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->phy_proc_rx,
|
|
"[eNB][total_phy_proc_rx]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ofdm_demod_stats,
|
|
"[eNB][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
|
|
//print_meas(&PHY_vars_eNB_g[eNB_id][0]->ulsch_channel_estimation_stats,"[eNB][channel_est]");
|
|
//print_meas(&PHY_vars_eNB_g[eNB_id][0]->ulsch_freq_offset_estimation_stats,"[eNB][freq_offset]");
|
|
//print_meas(&PHY_vars_eNB_g[eNB_id][0]->rx_dft_stats,"[eNB][rx_dft]");
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demodulation_stats,
|
|
"[eNB][demodulation]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_decoding_stats,
|
|
"[eNB][decoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_deinterleaving_stats,
|
|
"[eNB][|_deinterleaving]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_demultiplexing_stats,
|
|
"[eNB][|_demultiplexing]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_rate_unmatching_stats,
|
|
"[eNB][|_rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_turbo_decoding_stats,
|
|
"[eNB][|_turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_init_stats,
|
|
"[eNB][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_alpha_stats,
|
|
"[eNB][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_beta_stats,
|
|
"[eNB][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_gamma_stats,
|
|
"[eNB][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_ext_stats,
|
|
"[eNB][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl1_stats,
|
|
"[eNB][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->ulsch_tc_intl2_stats,
|
|
"[eNB][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&PHY_vars_eNB_g[eNB_id][0]->rx_prach, "[eNB][rx_prach]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
|
|
#ifdef LOCALIZATION
|
|
print_meas(&PHY_vars_eNB_g[eNB_id][0]->localization_stats, "[eNB][LOCALIZATION]",&oaisim_stats,&oaisim_stats_f);
|
|
#endif
|
|
}
|
|
|
|
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
|
|
|
print_meas (&UE_mac_inst[UE_id].ue_scheduler, "[UE][mac_scheduler]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu, "[UE][tx_ulsch_sdu]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu, "[UE][rx_dlsch_sdu]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_mac_inst[UE_id].ue_query_mch, "[UE][query_MCH]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_mac_inst[UE_id].rx_mch_sdu, "[UE][rx_mch_sdu]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_mac_inst[UE_id].rx_si, "[UE][rx_si]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
|
|
print_meas (&UE_pdcp_stats[UE_id].pdcp_run, "[UE][total_pdcp_run]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_pdcp_stats[UE_id].data_req, "[UE][DL][pdcp_data_req]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_pdcp_stats[UE_id].data_ind, "[UE][UL][pdcp_data_ind]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&UE_pdcp_stats[UE_id].apply_security,
|
|
"[UE][DL][apply_security]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_pdcp_stats[UE_id].validate_security,
|
|
"[UE][UL][validate_security]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
print_meas (&UE_pdcp_stats[UE_id].ip_pdcp, "[UE][DL][ip_pdcp]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&UE_pdcp_stats[UE_id].pdcp_ip, "[UE][UL][pdcp_ip]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
|
|
}
|
|
|
|
for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
|
|
|
|
print_meas (&eNB_mac_inst[eNB_id].eNB_scheduler, "[eNB][mac_scheduler]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_si, "[eNB][DL][SI]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_ra, "[eNB][DL][RA]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].fill_DLSCH_dci,
|
|
"[eNB][DL/UL][fill_DCI]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_dlsch_preprocessor,
|
|
"[eNB][DL][preprocessor]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_dlsch,
|
|
"[eNB][DL][schedule_tx_dlsch]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_mch, "[eNB][DL][mch]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].schedule_ulsch, "[eNB][UL][ULSCH]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_mac_inst[eNB_id].rx_ulsch_sdu,
|
|
"[eNB][UL][rx_ulsch_sdu]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&eNB_pdcp_stats[eNB_id].pdcp_run, "[eNB][pdcp_run]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_pdcp_stats[eNB_id].data_req,
|
|
"[eNB][DL][pdcp_data_req]", &oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_pdcp_stats[eNB_id].data_ind,
|
|
"[eNB][UL][pdcp_data_ind]", &oaisim_stats, &oaisim_stats_f);
|
|
|
|
print_meas (&eNB_pdcp_stats[eNB_id].apply_security,
|
|
"[eNB][DL][apply_security]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
print_meas (&eNB_pdcp_stats[eNB_id].validate_security,
|
|
"[eNB][UL][validate_security]", &oaisim_stats,
|
|
&oaisim_stats_f);
|
|
print_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp, "[eNB][DL][ip_pdcp]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
print_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip, "[eNB][UL][pdcp_ip]",
|
|
&oaisim_stats, &oaisim_stats_f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if !defined(ENABLE_ITTI)
|
|
static void *
|
|
sigh (void *arg)
|
|
{
|
|
|
|
int signum;
|
|
sigset_t sigcatch;
|
|
sigemptyset (&sigcatch);
|
|
sigaddset (&sigcatch, SIGHUP);
|
|
sigaddset (&sigcatch, SIGINT);
|
|
sigaddset (&sigcatch, SIGTERM);
|
|
sigaddset (&sigcatch, SIGQUIT);
|
|
|
|
for (;;) {
|
|
sigwait (&sigcatch, &signum);
|
|
|
|
//sigwait(&sigblock, &signum);
|
|
switch (signum) {
|
|
case SIGHUP:
|
|
case SIGINT:
|
|
case SIGTERM:
|
|
case SIGQUIT:
|
|
fprintf (stderr, "received signal %d \n", signum);
|
|
// no need for mutx: when ITTI not used, this variable is only accessed by this function
|
|
l2l1_state = L2L1_TERMINATED;
|
|
break;
|
|
|
|
default:
|
|
fprintf (stderr, "Unexpected signal %d \n", signum);
|
|
exit (-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
pthread_exit (NULL);
|
|
}
|
|
#endif /* !defined(ENABLE_ITTI) */
|
|
|
|
void
|
|
oai_shutdown (void)
|
|
{
|
|
static int done = 0;
|
|
|
|
if (done)
|
|
return;
|
|
|
|
free (otg_pdcp_buffer);
|
|
otg_pdcp_buffer = 0;
|
|
|
|
#ifdef SMBV
|
|
|
|
// Rohde&Schwarz SMBV100A vector signal generator
|
|
if (config_smbv) {
|
|
smbv_send_config (smbv_fname,smbv_ip);
|
|
}
|
|
|
|
#endif
|
|
|
|
//Perform KPI measurements
|
|
if (oai_emulation.info.otg_enabled == 1){
|
|
LOG_N(EMU,"calling OTG kpi gen .... \n");
|
|
kpi_gen ();
|
|
}
|
|
if (oai_emulation.info.opp_enabled == 1)
|
|
print_opp_meas_oaisim ();
|
|
|
|
// relase all rx state
|
|
if (ethernet_flag == 1) {
|
|
emu_transport_release ();
|
|
}
|
|
|
|
#ifdef PROC
|
|
|
|
if (abstraction_flag == 0 && Channel_Flag==0 && Process_Flag==0)
|
|
#else
|
|
if (abstraction_flag == 0)
|
|
#endif
|
|
{
|
|
/*
|
|
#ifdef IFFT_FPGA
|
|
free(txdataF2[0]);
|
|
free(txdataF2[1]);
|
|
free(txdataF2);
|
|
free(txdata[0]);
|
|
free(txdata[1]);
|
|
free(txdata);
|
|
#endif
|
|
*/
|
|
/*
|
|
for (int i = 0; i < 2; i++) {
|
|
free (s_re[i]);
|
|
free (s_im[i]);
|
|
free (r_re[i]);
|
|
free (r_im[i]);
|
|
}
|
|
|
|
free (s_re);
|
|
free (s_im);
|
|
free (r_re);
|
|
free (r_im);
|
|
s_re = 0;
|
|
s_im = 0;
|
|
r_re = 0;
|
|
r_im = 0;*/
|
|
|
|
lte_sync_time_free ();
|
|
}
|
|
|
|
// added for PHY abstraction
|
|
if (oai_emulation.info.ocm_enabled == 1) {
|
|
for (eNB_inst = 0; eNB_inst < NUMBER_OF_eNB_MAX; eNB_inst++) {
|
|
free (enb_data[eNB_inst]);
|
|
enb_data[eNB_inst] = 0;
|
|
}
|
|
|
|
for (UE_inst = 0; UE_inst < NUMBER_OF_UE_MAX; UE_inst++) {
|
|
free (ue_data[UE_inst]);
|
|
ue_data[UE_inst] = 0;
|
|
}
|
|
} //End of PHY abstraction changes
|
|
|
|
#ifdef OPENAIR2
|
|
mac_top_cleanup ();
|
|
#endif
|
|
|
|
// stop OMG
|
|
stop_mobility_generator (omg_param_list); //omg_param_list.mobility_type
|
|
#ifdef OPENAIR2
|
|
|
|
if (oai_emulation.info.omv_enabled == 1)
|
|
omv_end (pfd[1], omv_data);
|
|
|
|
#endif
|
|
|
|
if ((oai_emulation.info.ocm_enabled == 1) && (ethernet_flag == 0)
|
|
&& (ShaF != NULL)) {
|
|
destroyMat (ShaF, map1, map2);
|
|
ShaF = 0;
|
|
}
|
|
|
|
if (opt_enabled == 1)
|
|
terminate_opt ();
|
|
|
|
if (oai_emulation.info.cli_enabled)
|
|
cli_server_cleanup ();
|
|
|
|
for (int i = 0; i < NUMBER_OF_eNB_MAX + NUMBER_OF_UE_MAX; i++)
|
|
if (oai_emulation.info.oai_ifup[i] == 1) {
|
|
char interfaceName[8];
|
|
snprintf (interfaceName, sizeof(interfaceName), "oai%d", i);
|
|
bringInterfaceUp (interfaceName, 0);
|
|
}
|
|
|
|
log_thread_finalize ();
|
|
logClean ();
|
|
VCD_SIGNAL_DUMPER_CLOSE ();
|
|
|
|
done = 1; // prevent next invokation of this function
|
|
|
|
LOG_N(EMU,
|
|
">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU shutdown <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
|
|
}
|
|
|
|
eNB_MAC_INST*
|
|
get_eNB_mac_inst (module_id_t module_idP)
|
|
{
|
|
return (&eNB_mac_inst[module_idP]);
|
|
}
|
|
|
|
OAI_Emulation*
|
|
get_OAI_emulation ()
|
|
{
|
|
return &oai_emulation;
|
|
}
|
|
|
|
|