You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

702 lines
38 KiB
C++

/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/common/common_helper.h"
#include "srslte/common/config_file.h"
#include "srslte/common/crash_handler.h"
#include "srslte/common/logger_srslog_wrapper.h"
#include "srslte/common/logmap.h"
#include "srslte/common/metrics_hub.h"
#include "srslte/common/signal_handler.h"
#include "srslte/srslog/srslog.h"
#include "srslte/srslte.h"
#include "srslte/version.h"
#include "srsue/hdr/metrics_csv.h"
#include "srsue/hdr/metrics_stdout.h"
#include "srsue/hdr/ue.h"
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
extern bool simulate_rlf;
using namespace std;
using namespace srsue;
namespace bpo = boost::program_options;
/**********************************************************************
* Local static variables
***********************************************************************/
static bool do_metrics = false;
static metrics_stdout* metrics_screen = nullptr;
/**********************************************************************
* Program arguments processing
***********************************************************************/
string config_file;
static int parse_args(all_args_t* args, int argc, char* argv[])
{
bool use_standard_lte_rates = false;
8 years ago
// Command line only options
bpo::options_description general("General options");
general.add_options()("help,h", "Produce help message")("version,v", "Print version information and exit");
8 years ago
// Command line or config file options
bpo::options_description common("Configuration options");
// clang-format off
8 years ago
common.add_options()
("ue.radio", bpo::value<string>(&args->rf.type)->default_value("multi"), "Type of the radio [multi]")
("ue.phy", bpo::value<string>(&args->phy.type)->default_value("lte"), "Type of the PHY [lte]")
("ue.stack", bpo::value<string>(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]")
("rf.dl_earfcn", bpo::value<string>(&args->phy.dl_earfcn)->default_value("3400"), "Downlink EARFCN list")
("rf.ul_earfcn", bpo::value<string>(&args->phy.ul_earfcn), "Uplink EARFCN list. Optional.")
("rf.dl_nr_arfcn", bpo::value<string>(&args->phy.dl_nr_arfcn)->default_value("632628"), "Downlink NR-ARFCN list")
("rf.srate", bpo::value<double>(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz")
("rf.freq_offset", bpo::value<float>(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset")
("rf.dl_freq", bpo::value<float>(&args->phy.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)")
("rf.ul_freq", bpo::value<float>(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)")
("rf.rx_gain", bpo::value<float>(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain")
("rf.tx_gain", bpo::value<float>(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain (all channels)")
("rf.tx_gain[0]", bpo::value<float>(&args->rf.tx_gain_ch[0])->default_value(-1), "Front-end transmitter gain CH0")
("rf.tx_gain[1]", bpo::value<float>(&args->rf.tx_gain_ch[1])->default_value(-1), "Front-end transmitter gain CH1")
("rf.tx_gain[2]", bpo::value<float>(&args->rf.tx_gain_ch[2])->default_value(-1), "Front-end transmitter gain CH2")
("rf.tx_gain[3]", bpo::value<float>(&args->rf.tx_gain_ch[3])->default_value(-1), "Front-end transmitter gain CH3")
("rf.tx_gain[4]", bpo::value<float>(&args->rf.tx_gain_ch[4])->default_value(-1), "Front-end transmitter gain CH4")
("rf.rx_gain[0]", bpo::value<float>(&args->rf.rx_gain_ch[0])->default_value(-1), "Front-end receiver gain CH0")
("rf.rx_gain[1]", bpo::value<float>(&args->rf.rx_gain_ch[1])->default_value(-1), "Front-end receiver gain CH1")
("rf.rx_gain[2]", bpo::value<float>(&args->rf.rx_gain_ch[2])->default_value(-1), "Front-end receiver gain CH2")
("rf.rx_gain[3]", bpo::value<float>(&args->rf.rx_gain_ch[3])->default_value(-1), "Front-end receiver gain CH3")
("rf.rx_gain[4]", bpo::value<float>(&args->rf.rx_gain_ch[4])->default_value(-1), "Front-end receiver gain CH4")
("rf.nof_carriers", bpo::value<uint32_t>(&args->rf.nof_carriers)->default_value(1), "Number of carriers")
("rf.nof_antennas", bpo::value<uint32_t>(&args->rf.nof_antennas)->default_value(1), "Number of antennas per carrier")
8 years ago
("rf.device_name", bpo::value<string>(&args->rf.device_name)->default_value("auto"), "Front-end device name")
("rf.device_args", bpo::value<string>(&args->rf.device_args)->default_value("auto"), "Front-end device arguments")
("rf.time_adv_nsamples", bpo::value<string>(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance")
("rf.continuous_tx", bpo::value<string>(&args->rf.continuous_tx)->default_value("auto"), "Transmit samples continuously to the radio or on bursts (auto/yes/no). Default is auto (yes for UHD, no for rest)")
("rf.bands.rx[0].min", bpo::value<float>(&args->rf.ch_rx_bands[0].min)->default_value(0), "Lower frequency boundary for CH0-RX")
("rf.bands.rx[0].max", bpo::value<float>(&args->rf.ch_rx_bands[0].max)->default_value(0), "Higher frequency boundary for CH0-RX")
("rf.bands.rx[1].min", bpo::value<float>(&args->rf.ch_rx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-RX")
("rf.bands.rx[1].max", bpo::value<float>(&args->rf.ch_rx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-RX")
("rf.bands.rx[2].min", bpo::value<float>(&args->rf.ch_rx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-RX")
("rf.bands.rx[2].max", bpo::value<float>(&args->rf.ch_rx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-RX")
("rf.bands.rx[3].min", bpo::value<float>(&args->rf.ch_rx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-RX")
("rf.bands.rx[3].max", bpo::value<float>(&args->rf.ch_rx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-RX")
("rf.bands.rx[4].min", bpo::value<float>(&args->rf.ch_rx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-RX")
("rf.bands.rx[4].max", bpo::value<float>(&args->rf.ch_rx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-RX")
("rf.bands.tx[0].min", bpo::value<float>(&args->rf.ch_tx_bands[0].min)->default_value(0), "Lower frequency boundary for CH1-TX")
("rf.bands.tx[0].max", bpo::value<float>(&args->rf.ch_tx_bands[0].max)->default_value(0), "Higher frequency boundary for CH1-TX")
("rf.bands.tx[1].min", bpo::value<float>(&args->rf.ch_tx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-TX")
("rf.bands.tx[1].max", bpo::value<float>(&args->rf.ch_tx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-TX")
("rf.bands.tx[2].min", bpo::value<float>(&args->rf.ch_tx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-TX")
("rf.bands.tx[2].max", bpo::value<float>(&args->rf.ch_tx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-TX")
("rf.bands.tx[3].min", bpo::value<float>(&args->rf.ch_tx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-TX")
("rf.bands.tx[3].max", bpo::value<float>(&args->rf.ch_tx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-TX")
("rf.bands.tx[4].min", bpo::value<float>(&args->rf.ch_tx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-TX")
("rf.bands.tx[4].max", bpo::value<float>(&args->rf.ch_tx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-TX")
("rrc.feature_group", bpo::value<uint32_t>(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the"
"UECapabilityInformation message. Default 0xe6041000")
("rrc.ue_category", bpo::value<string>(&args->stack.rrc.ue_category_str)->default_value(SRSLTE_UE_CATEGORY_DEFAULT), "UE Category (1 to 10)")
("rrc.ue_category_dl", bpo::value<int>(&args->stack.rrc.ue_category_dl)->default_value(-1), "UE Category DL v12 (valid values: 0, 4, 6, 7, 9 to 16)")
("rrc.ue_category_ul", bpo::value<int>(&args->stack.rrc.ue_category_ul)->default_value(-1), "UE Category UL v12 (valid values: 0, 3, 5, 7, 8 and 13)")
("rrc.release", bpo::value<uint32_t>(&args->stack.rrc.release)->default_value(SRSLTE_RELEASE_DEFAULT), "UE Release (8 to 12)")
("rrc.mbms_service_id", bpo::value<int32_t>(&args->stack.rrc.mbms_service_id)->default_value(-1), "MBMS service id for autostart (-1 means disabled)")
("rrc.mbms_service_port", bpo::value<uint32_t>(&args->stack.rrc.mbms_service_port)->default_value(4321), "Port of the MBMS service")
("nas.apn", bpo::value<string>(&args->stack.nas.apn_name)->default_value(""), "Set Access Point Name (APN) for data services")
("nas.apn_protocol", bpo::value<string>(&args->stack.nas.apn_protocol)->default_value(""), "Set Access Point Name (APN) protocol for data services")
("nas.user", bpo::value<string>(&args->stack.nas.apn_user)->default_value(""), "Username for CHAP authentication")
("nas.pass", bpo::value<string>(&args->stack.nas.apn_pass)->default_value(""), "Password for CHAP authentication")
("nas.force_imsi_attach", bpo::value<bool>(&args->stack.nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach")
("nas.eia", bpo::value<string>(&args->stack.nas.eia)->default_value("1,2,3"), "List of integrity algorithms included in UE capabilities")
("nas.eea", bpo::value<string>(&args->stack.nas.eea)->default_value("0,1,2,3"), "List of ciphering algorithms included in UE capabilities")
("pcap.enable", bpo::value<bool>(&args->stack.pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark")
("pcap.filename", bpo::value<string>(&args->stack.pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename")
("pcap.nas_enable", bpo::value<bool>(&args->stack.pcap.nas_enable)->default_value(false), "Enable NAS packet captures for wireshark")
("pcap.nas_filename", bpo::value<string>(&args->stack.pcap.nas_filename)->default_value("ue_nas.pcap"), "NAS layer capture filename (useful when NAS encryption is enabled)")
8 years ago
("gui.enable", bpo::value<bool>(&args->gui.enable)->default_value(false), "Enable GUI plots")
("log.rf_level", bpo::value<string>(&args->rf.log_level), "RF log level")
("log.phy_level", bpo::value<string>(&args->phy.log.phy_level), "PHY log level")
("log.phy_lib_level", bpo::value<string>(&args->phy.log.phy_lib_level), "PHY lib log level")
("log.phy_hex_limit", bpo::value<int>(&args->phy.log.phy_hex_limit), "PHY log hex dump limit")
("log.mac_level", bpo::value<string>(&args->stack.log.mac_level), "MAC log level")
("log.mac_hex_limit", bpo::value<int>(&args->stack.log.mac_hex_limit), "MAC log hex dump limit")
("log.rlc_level", bpo::value<string>(&args->stack.log.rlc_level), "RLC log level")
("log.rlc_hex_limit", bpo::value<int>(&args->stack.log.rlc_hex_limit), "RLC log hex dump limit")
("log.pdcp_level", bpo::value<string>(&args->stack.log.pdcp_level), "PDCP log level")
("log.pdcp_hex_limit", bpo::value<int>(&args->stack.log.pdcp_hex_limit), "PDCP log hex dump limit")
("log.rrc_level", bpo::value<string>(&args->stack.log.rrc_level), "RRC log level")
("log.rrc_hex_limit", bpo::value<int>(&args->stack.log.rrc_hex_limit), "RRC log hex dump limit")
("log.gw_level", bpo::value<string>(&args->gw.log.gw_level), "GW log level")
("log.gw_hex_limit", bpo::value<int>(&args->gw.log.gw_hex_limit), "GW log hex dump limit")
("log.nas_level", bpo::value<string>(&args->stack.log.nas_level), "NAS log level")
("log.nas_hex_limit", bpo::value<int>(&args->stack.log.nas_hex_limit), "NAS log hex dump limit")
("log.usim_level", bpo::value<string>(&args->stack.log.usim_level), "USIM log level")
("log.usim_hex_limit", bpo::value<int>(&args->stack.log.usim_hex_limit), "USIM log hex dump limit")
("log.stack_level", bpo::value<string>(&args->stack.log.stack_level), "Stack log level")
("log.stack_hex_limit", bpo::value<int>(&args->stack.log.stack_hex_limit), "Stack log hex dump limit")
8 years ago
("log.all_level", bpo::value<string>(&args->log.all_level)->default_value("info"), "ALL log level")
("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit")
("log.filename", bpo::value<string>(&args->log.filename)->default_value("/tmp/ue.log"), "Log filename")
("log.file_max_size", bpo::value<int>(&args->log.file_max_size)->default_value(-1), "Maximum file size (in kilobytes). When passed, multiple files are created. Default -1 (single file)")
8 years ago
("usim.mode", bpo::value<string>(&args->stack.usim.mode)->default_value("soft"), "USIM mode (soft or pcsc)")
("usim.algo", bpo::value<string>(&args->stack.usim.algo), "USIM authentication algorithm")
("usim.op", bpo::value<string>(&args->stack.usim.op), "USIM operator code")
("usim.opc", bpo::value<string>(&args->stack.usim.opc), "USIM operator code (ciphered variant)")
("usim.imsi", bpo::value<string>(&args->stack.usim.imsi), "USIM IMSI")
("usim.imei", bpo::value<string>(&args->stack.usim.imei), "USIM IMEI")
("usim.k", bpo::value<string>(&args->stack.usim.k), "USIM K")
("usim.pin", bpo::value<string>(&args->stack.usim.pin), "PIN in case real SIM card is used")
("usim.reader", bpo::value<string>(&args->stack.usim.reader)->default_value(""), "Force specific PCSC reader. Default: Try all available readers.")
("gw.netns", bpo::value<string>(&args->gw.netns)->default_value(""), "Network namespace to for TUN device (empty for default netns)")
("gw.ip_devname", bpo::value<string>(&args->gw.tun_dev_name)->default_value("tun_srsue"), "Name of the tun_srsue device")
("gw.ip_netmask", bpo::value<string>(&args->gw.tun_dev_netmask)->default_value("255.255.255.0"), "Netmask of the tun_srsue device")
/* Downlink Channel emulator section */
("channel.dl.enable", bpo::value<bool>(&args->phy.dl_channel_args.enable)->default_value(false), "Enable/Disable internal Downlink channel emulator")
("channel.dl.awgn.enable", bpo::value<bool>(&args->phy.dl_channel_args.awgn_enable)->default_value(false), "Enable/Disable AWGN simulator")
("channel.dl.awgn.snr", bpo::value<float>(&args->phy.dl_channel_args.awgn_snr_dB)->default_value(30.0f), "SNR in dB")
("channel.dl.awgn.signal_power", bpo::value<float>(&args->phy.dl_channel_args.awgn_signal_power_dBfs)->default_value(0.0f), "Received signal power in decibels full scale (dBfs)")
("channel.dl.fading.enable", bpo::value<bool>(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model")
("channel.dl.fading.model", bpo::value<std::string>(&args->phy.dl_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)")
("channel.dl.delay.enable", bpo::value<bool>(&args->phy.dl_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator")
("channel.dl.delay.period_s", bpo::value<float>(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.dl.delay.init_time_s", bpo::value<float>(&args->phy.dl_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds")
("channel.dl.delay.maximum_us", bpo::value<float>(&args->phy.dl_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds")
("channel.dl.delay.minimum_us", bpo::value<float>(&args->phy.dl_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds")
("channel.dl.rlf.enable", bpo::value<bool>(&args->phy.dl_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator")
("channel.dl.rlf.t_on_ms", bpo::value<uint32_t >(&args->phy.dl_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)")
("channel.dl.rlf.t_off_ms", bpo::value<uint32_t >(&args->phy.dl_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)")
("channel.dl.hst.enable", bpo::value<bool>(&args->phy.dl_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator")
("channel.dl.hst.period_s", bpo::value<float>(&args->phy.dl_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds")
("channel.dl.hst.fd_hz", bpo::value<float>(&args->phy.dl_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz")
("channel.dl.hst.init_time_s", bpo::value<float>(&args->phy.dl_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds")
/* Uplink Channel emulator section */
("channel.ul.enable", bpo::value<bool>(&args->phy.ul_channel_args.enable)->default_value(false), "Enable/Disable internal Downlink channel emulator")
("channel.ul.awgn.enable", bpo::value<bool>(&args->phy.ul_channel_args.awgn_enable)->default_value(false), "Enable/Disable AWGN simulator")
("channel.ul.awgn.snr", bpo::value<float>(&args->phy.ul_channel_args.awgn_snr_dB)->default_value(30.0f), "Noise level in decibels full scale (dBfs)")
("channel.ul.awgn.signal_power", bpo::value<float>(&args->phy.ul_channel_args.awgn_signal_power_dBfs)->default_value(30.0f), "Transmitted signal power in decibels full scale (dBfs)")
("channel.ul.fading.enable", bpo::value<bool>(&args->phy.ul_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model")
("channel.ul.fading.model", bpo::value<std::string>(&args->phy.ul_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)")
("channel.ul.delay.enable", bpo::value<bool>(&args->phy.ul_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator")
("channel.ul.delay.period_s", bpo::value<float>(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)")
("channel.ul.delay.init_time_s", bpo::value<float>(&args->phy.ul_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds")
("channel.ul.delay.maximum_us", bpo::value<float>(&args->phy.ul_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds")
("channel.ul.delay.minimum_us", bpo::value<float>(&args->phy.ul_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds")
("channel.ul.rlf.enable", bpo::value<bool>(&args->phy.ul_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator")
("channel.ul.rlf.t_on_ms", bpo::value<uint32_t >(&args->phy.ul_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)")
("channel.ul.rlf.t_off_ms", bpo::value<uint32_t >(&args->phy.ul_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)")
("channel.ul.hst.enable", bpo::value<bool>(&args->phy.ul_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator")
("channel.ul.hst.period_s", bpo::value<float>(&args->phy.ul_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds")
("channel.ul.hst.fd_hz", bpo::value<float>(&args->phy.ul_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz")
("channel.ul.hst.init_time_s", bpo::value<float>(&args->phy.ul_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds")
/* PHY section */
("phy.worker_cpu_mask",
bpo::value<int>(&args->phy.worker_cpu_mask)->default_value(-1),
8 years ago
"cpu bit mask (eg 255 = 1111 1111)")
("phy.sync_cpu_affinity",
bpo::value<int>(&args->phy.sync_cpu_affinity)->default_value(-1),
8 years ago
"index of the core used by the sync thread")
("phy.rx_gain_offset",
bpo::value<float>(&args->phy.rx_gain_offset)->default_value(62),
"RX Gain offset to add to rx_gain to correct RSRP value")
("phy.prach_gain",
bpo::value<float>(&args->phy.prach_gain)->default_value(-1.0),
8 years ago
"Disable PRACH power control")
("phy.cqi_max",
bpo::value<int>(&args->phy.cqi_max)->default_value(15),
8 years ago
"Upper bound on the maximum CQI to be reported. Default 15.")
("phy.cqi_fixed",
bpo::value<int>(&args->phy.cqi_fixed)->default_value(-1),
8 years ago
"Fixes the reported CQI to a constant value. Default disabled.")
("phy.sfo_correct_period",
bpo::value<uint32_t>(&args->phy.sfo_correct_period)->default_value(DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD),
"Period in ms to correct sample time")
("phy.sfo_emma",
bpo::value<float>(&args->phy.sfo_ema)->default_value(DEFAULT_SFO_EMA_COEFF),
"EMA coefficient to average sample offsets used to compute SFO")
("phy.snr_ema_coeff",
bpo::value<float>(&args->phy.snr_ema_coeff)->default_value(0.1),
8 years ago
"Sets the SNR exponential moving average coefficient (Default 0.1)")
("phy.snr_estim_alg",
bpo::value<string>(&args->phy.snr_estim_alg)->default_value("refs"),
8 years ago
"Sets the noise estimation algorithm. (Default refs)")
("phy.pdsch_max_its",
bpo::value<uint32_t>(&args->phy.pdsch_max_its)->default_value(8),
8 years ago
"Maximum number of turbo decoder iterations")
("phy.meas_evm",
bpo::value<bool>(&args->phy.meas_evm)->default_value(false),
"Measure PDSCH EVM, increases CPU load (default false)")
("phy.nof_phy_threads",
bpo::value<uint32_t>(&args->phy.nof_phy_threads)->default_value(3),
8 years ago
"Number of PHY threads")
("phy.equalizer_mode",
bpo::value<string>(&args->phy.equalizer_mode)->default_value("mmse"),
8 years ago
"Equalizer mode")
("phy.intra_freq_meas_len_ms",
bpo::value<uint32_t>(&args->phy.intra_freq_meas_len_ms)->default_value(20),
"Duration of the intra-frequency neighbour cell measurement in ms.")
("phy.intra_freq_meas_period_ms",
bpo::value<uint32_t>(&args->phy.intra_freq_meas_period_ms)->default_value(200),
"Period of intra-frequency neighbour cell measurement in ms. Maximum as per 3GPP is 200 ms.")
("phy.correct_sync_error",
bpo::value<bool>(&args->phy.correct_sync_error)->default_value(false),
"Channel estimator measures and pre-compensates time synchronization error. Increases CPU usage, improves PDSCH "
"decoding in high SFO and high speed UE scenarios.")
("phy.cfo_is_doppler",
bpo::value<bool>(&args->phy.cfo_is_doppler)->default_value(false),
"Assume detected CFO is doppler and correct the UL in the same direction. If disabled, the CFO is assumed"
"to be caused by the local oscillator and the UL correction is in the opposite direction. Default assumes oscillator.")
("phy.cfo_integer_enabled",
bpo::value<bool>(&args->phy.cfo_integer_enabled)->default_value(false),
8 years ago
"Enables integer CFO estimation and correction.")
("phy.cfo_correct_tol_hz",
bpo::value<float>(&args->phy.cfo_correct_tol_hz)->default_value(1.0),
"Tolerance (in Hz) for digital CFO compensation (needs to be low if interpolate_subframe_enabled=true.")
8 years ago
("phy.cfo_pss_ema",
bpo::value<float>(&args->phy.cfo_pss_ema)->default_value(DEFAULT_CFO_EMA_TRACK),
"CFO Exponential Moving Average coefficient for PSS estimation during TRACK.")
("phy.cfo_ref_mask",
bpo::value<uint32_t>(&args->phy.cfo_ref_mask)->default_value(1023),
"Bitmask for subframes on which to run RS estimation (set to 0 to disable, default all sf)")
("phy.cfo_loop_bw_pss",
bpo::value<float>(&args->phy.cfo_loop_bw_pss)->default_value(DEFAULT_CFO_BW_PSS),
"CFO feedback loop bandwidth for samples from PSS")
("phy.cfo_loop_bw_ref",
bpo::value<float>(&args->phy.cfo_loop_bw_ref)->default_value(DEFAULT_CFO_BW_REF),
"CFO feedback loop bandwidth for samples from RS")
("phy.cfo_loop_pss_tol",
bpo::value<float>(&args->phy.cfo_loop_pss_tol)->default_value(DEFAULT_CFO_PSS_MIN),
"Tolerance (in Hz) of the PSS estimation method. Below this value, PSS estimation does not feeds back the loop"
"and RS estimations are used instead (when available)")
("phy.cfo_loop_ref_min",
bpo::value<float>(&args->phy.cfo_loop_ref_min)->default_value(DEFAULT_CFO_REF_MIN),
"Tolerance (in Hz) of the RS estimation method. Below this value, RS estimation does not feeds back the loop")
("phy.cfo_loop_pss_conv",
bpo::value<uint32_t>(&args->phy.cfo_loop_pss_conv)->default_value(DEFAULT_PSS_STABLE_TIMEOUT),
"After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.")
("phy.interpolate_subframe_enabled",
bpo::value<bool>(&args->phy.interpolate_subframe_enabled)->default_value(false),
"Interpolates in the time domain the channel estimates within 1 subframe.")
("phy.estimator_fil_auto",
bpo::value<bool>(&args->phy.estimator_fil_auto)->default_value(false),
"The channel estimator smooths the channel estimate with an adaptative filter.")
("phy.estimator_fil_stddev",
bpo::value<float>(&args->phy.estimator_fil_stddev)->default_value(1.0f),
"Sets the channel estimator smooth gaussian filter standard deviation.")
("phy.estimator_fil_order",
bpo::value<uint32_t>(&args->phy.estimator_fil_order)->default_value(4),
"Sets the channel estimator smooth gaussian filter order (even values perform better).")
("phy.snr_to_cqi_offset",
bpo::value<float>(&args->phy.snr_to_cqi_offset)->default_value(0),
"Sets an offset in the SNR to CQI table. This is used to adjust the reported CQI.")
("phy.sss_algorithm",
bpo::value<string>(&args->phy.sss_algorithm)->default_value("full"),
8 years ago
"Selects the SSS estimation algorithm.")
("phy.pdsch_csi_enabled",
bpo::value<bool>(&args->phy.pdsch_csi_enabled)->default_value(true),
"Stores the Channel State Information and uses it for weightening the softbits. It is only used in TM1.")
8 years ago
("phy.pdsch_8bit_decoder",
bpo::value<bool>(&args->phy.pdsch_8bit_decoder)->default_value(false),
"Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)")
("phy.force_ul_amplitude",
bpo::value<float>(&args->phy.force_ul_amplitude)->default_value(0.0),
"Forces the peak amplitude in the PUCCH, PUSCH and SRS (set 0.0 to 1.0, set to 0 or negative for disabling)")
8 years ago
("phy.in_sync_rsrp_dbm_th",
bpo::value<float>(&args->phy.in_sync_rsrp_dbm_th)->default_value(-130.0f),
"RSRP threshold (in dBm) above which the UE considers to be in-sync")
("phy.in_sync_snr_db_th",
bpo::value<float>(&args->phy.in_sync_snr_db_th)->default_value(3.0f),
"SNR threshold (in dB) above which the UE considers to be in-sync")
("phy.nof_in_sync_events",
bpo::value<uint32_t>(&args->phy.nof_in_sync_events)->default_value(10),
"Number of PHY in-sync events before sending an in-sync event to RRC")
("phy.nof_out_of_sync_events",
bpo::value<uint32_t>(&args->phy.nof_out_of_sync_events)->default_value(20),
"Number of PHY out-sync events before sending an out-sync event to RRC")
("expert.lte_sample_rates",
bpo::value<bool>(&use_standard_lte_rates)->default_value(false),
"Whether to use default LTE sample rates instead of shorter variants.")
// UE simulation args
("sim.airplane_t_on_ms",
bpo::value<int>(&args->stack.nas.sim.airplane_t_on_ms)->default_value(-1),
"On-time for airplane mode (in ms)")
("sim.airplane_t_off_ms",
bpo::value<int>(&args->stack.nas.sim.airplane_t_off_ms)->default_value(-1),
"Off-time for airplane mode (in ms)")
/* general options */
("general.metrics_period_secs",
bpo::value<float>(&args->general.metrics_period_secs)->default_value(1.0),
"Periodicity for metrics in seconds")
("general.metrics_csv_enable",
bpo::value<bool>(&args->general.metrics_csv_enable)->default_value(false),
"Write UE metrics to CSV file")
("general.metrics_csv_filename",
bpo::value<string>(&args->general.metrics_csv_filename)->default_value("/tmp/ue_metrics.csv"),
"Metrics CSV filename")
("general.metrics_csv_append",
bpo::value<bool>(&args->general.metrics_csv_append)->default_value(false),
"Set to true to append new output to existing CSV file")
("general.metrics_csv_flush_period_sec",
bpo::value<int>(&args->general.metrics_csv_flush_period_sec)->default_value(-1),
5 years ago
"Periodicity in s to flush CSV file to disk (-1 for auto)")
("stack.have_tti_time_stats",
bpo::value<bool>(&args->stack.have_tti_time_stats)->default_value(true),
"Calculate TTI execution statistics")
// NR params
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("ue"), "VNF instance type [gnb,ue]")
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface")
("vnf.port", bpo::value<uint16_t>(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port")
("nr.nof_carriers", bpo::value<uint32_t>(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers")
("nr.nof_prb", bpo::value<uint32_t>(&args->phy.nr_nof_prb)->default_value(50), "NR carrier bandwidth")
("nr.freq", bpo::value<double>(&args->phy.nr_freq_hz)->default_value(2630e6), "NR carrier bandwidth")
;
8 years ago
// Positional options - config file location
bpo::options_description position("Positional options");
position.add_options()
("config_file", bpo::value<string>(&config_file), "UE configuration file");
// clang-format on
8 years ago
bpo::positional_options_description p;
p.add("config_file", -1);
// these options are allowed on the command line
bpo::options_description cmdline_options;
cmdline_options.add(common).add(position).add(general);
// parse the command line and store result in vm
bpo::variables_map vm;
try {
bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm);
bpo::notify(vm);
} catch (bpo::error& e) {
cerr << e.what() << endl;
return SRSLTE_ERROR;
}
8 years ago
// help option was given - print usage and exit
if (vm.count("help")) {
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
cout << common << endl << general << endl;
exit(SRSLTE_SUCCESS);
8 years ago
}
8 years ago
// print version number and exit
if (vm.count("version")) {
cout << "Version " << srslte_get_version_major() << "." << srslte_get_version_minor() << "."
<< srslte_get_version_patch() << endl;
exit(SRSLTE_SUCCESS);
8 years ago
}
// if no config file given, check users home path
8 years ago
if (!vm.count("config_file")) {
if (!config_exists(config_file, "ue.conf")) {
cout << "Failed to read UE configuration file " << config_file << " - exiting" << endl;
return SRSLTE_ERROR;
}
8 years ago
}
cout << "Reading configuration file " << config_file << "..." << endl;
ifstream conf(config_file.c_str(), ios::in);
if (conf.fail()) {
cout << "Failed to read configuration file " << config_file << " - exiting" << endl;
return SRSLTE_ERROR;
}
// parse config file and handle errors gracefully
try {
bpo::store(bpo::parse_config_file(conf, common), vm);
bpo::notify(vm);
} catch (const boost::program_options::error& e) {
cerr << e.what() << endl;
return SRSLTE_ERROR;
}
// Check conflicting OP/OPc options and which is being used
if (vm.count("usim.op") && !vm["usim.op"].defaulted() && vm.count("usim.opc") && !vm["usim.opc"].defaulted()) {
cout << "Conflicting options OP and OPc. Please configure either one or the other." << endl;
return SRSLTE_ERROR;
} else {
args->stack.usim.using_op = vm.count("usim.op");
}
8 years ago
// Apply all_level to any unset layers
if (vm.count("log.all_level")) {
if (!vm.count("log.rf_level")) {
args->rf.log_level = args->log.all_level;
}
if (!vm.count("log.phy_level")) {
args->phy.log.phy_level = args->log.all_level;
}
if (!vm.count("log.phy_lib_level")) {
args->phy.log.phy_lib_level = args->log.all_level;
}
8 years ago
if (!vm.count("log.mac_level")) {
args->stack.log.mac_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.rlc_level")) {
args->stack.log.rlc_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.pdcp_level")) {
args->stack.log.pdcp_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.rrc_level")) {
args->stack.log.rrc_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.nas_level")) {
args->stack.log.nas_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.gw_level")) {
args->gw.log.gw_level = args->log.all_level;
}
8 years ago
if (!vm.count("log.usim_level")) {
args->stack.log.usim_level = args->log.all_level;
8 years ago
}
if (!vm.count("log.stack_level")) {
args->stack.log.stack_level = args->log.all_level;
}
8 years ago
}
8 years ago
// Apply all_hex_limit to any unset layers
if (vm.count("log.all_hex_limit")) {
if (!vm.count("log.phy_hex_limit")) {
args->phy.log.phy_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.mac_hex_limit")) {
args->stack.log.mac_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.rlc_hex_limit")) {
args->stack.log.rlc_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.pdcp_hex_limit")) {
args->stack.log.pdcp_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.rrc_hex_limit")) {
args->stack.log.rrc_hex_limit = args->log.all_hex_limit;
}
8 years ago
if (!vm.count("log.nas_hex_limit")) {
args->stack.log.nas_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.gw_hex_limit")) {
args->gw.log.gw_hex_limit = args->log.all_hex_limit;
8 years ago
}
if (!vm.count("log.usim_hex_limit")) {
args->stack.log.usim_hex_limit = args->log.all_hex_limit;
}
if (!vm.count("log.stack_hex_limit")) {
args->stack.log.stack_hex_limit = args->log.all_hex_limit;
}
}
// Set sync queue capacity to 1 for ZMQ
if (args->rf.device_name == "zmq") {
args->stack.sync_queue_size = 1;
} else {
// use default size
args->stack.sync_queue_size = MULTIQUEUE_DEFAULT_CAPACITY;
}
srslte_use_standard_symbol_size(use_standard_lte_rates);
return SRSLTE_SUCCESS;
}
static void* input_loop(void*)
{
string key;
8 years ago
while (running) {
getline(cin, key);
if (cin.eof() || cin.bad()) {
cout << "Closing stdin thread." << endl;
break;
} else {
if (key == "t") {
do_metrics = !do_metrics;
if (do_metrics) {
cout << "Enter t to stop trace." << endl;
} else {
cout << "Enter t to restart trace." << endl;
}
if (metrics_screen) {
metrics_screen->toggle_print(do_metrics);
}
} else if (key == "rlf") {
simulate_rlf = true;
cout << "Sending Radio Link Failure" << endl;
} else if (key == "q") {
// let the signal handler do the job
raise(SIGTERM);
}
}
}
return nullptr;
}
/// Adjusts the input value in args from kbytes to bytes.
static size_t fixup_log_file_maxsize(int x)
{
return (x < 0) ? 0 : size_t(x) * 1024u;
}
int main(int argc, char* argv[])
{
srslte_register_signal_handler();
srslte_debug_handle_crash(argc, argv);
all_args_t args = {};
if (int err = parse_args(&args, argc, argv)) {
return err;
}
// Setup logging.
log_sink = (args.log.filename == "stdout")
? srslog::create_stdout_sink()
: srslog::create_file_sink(args.log.filename, fixup_log_file_maxsize(args.log.file_max_size));
if (!log_sink) {
return SRSLTE_ERROR;
}
srslog::log_channel* chan = srslog::create_log_channel("main_channel", *log_sink);
if (!chan) {
return SRSLTE_ERROR;
}
srslte::srslog_wrapper log_wrapper(*chan);
Upgrade loggers in srsue (#2163) * Replaced UE logger in the ue class. * Replaced loggers in the main phy class and prach. * Replaced loggers in phy common and ta_control. * Replace loggers in cc and sf workers. * Replaced loggers in intra_measure, scell_recv, search, sfn_sync, sync. * Remove last uses of the old loggers in the main phy class. * Remove stray newline in logs. * Replaced loggers in ue gw. * - Started to replace loggers in the ue stack. - Replaced loggers in usim and pcsc. - Adapted nas and usim tests. * Replace loggers in nas. * Added missing log init calls in two previously modified tests. * Replaced logger in nas idle procs. * Replaced loggers in nas emm state. * Replaced loggers in tft packet filter and adapted tft test. * Replaced loggers in main RRC class. * Replaced loggers in RRC cell. * Replaced loggers in RRC meas. * Replaced loggers in rrc procedures. * Started logger replacement in MAC layer, more precisely in demux and dl_harq classes. Been unable to inject loggers in construction for dl_tb_process due to very weird static assertions in the std::vector code being the type not constructible which is not true, so instead use the main MAC logger directly. * Replaced loggers in mac mux class. * Replaced loggers in mac pro_bsr. * Replaced loggers in mac proc phr. * Replaced loggers in mac proc SR and RA. * Replace loggers in mac UL HARQ. * Replaced loggers in main ue stack class. * Fixed nas test crashing due to a null string. * Ported mac_test to use the new loggers. * Removed TTI reporting for the PHY log as the old logger did. * Replaced loggers in UE phy tests. * Configure loggers in nas_test. * Replaced loggers in rrc_meas_test. * Replaced loggers in rrc_reconfig_test. * Added missing newline in tft_test. * Fix compilation errors in TTCN3 tests. * Fix linker error detected in CI and warning. * Replaced loggers in TTCN3 tests. * Fix a text replace error in some log messages. * Remove trailing newlines from log entries. * Remove old logger from rrc. * Flush backend before printing the test status. * - Fix compilation error from previous rebase. - Remove trailing newlines from some missing log entries.
4 years ago
srslog::set_default_sink(*log_sink);
// Start the log backend.
srslog::init();
srslte::logmap::set_default_logger(&log_wrapper);
srslte::log_args(argc, argv, "UE");
srslte::check_scaling_governor(args.rf.device_name);
// Create UE instance
Upgrade loggers in srsue (#2163) * Replaced UE logger in the ue class. * Replaced loggers in the main phy class and prach. * Replaced loggers in phy common and ta_control. * Replace loggers in cc and sf workers. * Replaced loggers in intra_measure, scell_recv, search, sfn_sync, sync. * Remove last uses of the old loggers in the main phy class. * Remove stray newline in logs. * Replaced loggers in ue gw. * - Started to replace loggers in the ue stack. - Replaced loggers in usim and pcsc. - Adapted nas and usim tests. * Replace loggers in nas. * Added missing log init calls in two previously modified tests. * Replaced logger in nas idle procs. * Replaced loggers in nas emm state. * Replaced loggers in tft packet filter and adapted tft test. * Replaced loggers in main RRC class. * Replaced loggers in RRC cell. * Replaced loggers in RRC meas. * Replaced loggers in rrc procedures. * Started logger replacement in MAC layer, more precisely in demux and dl_harq classes. Been unable to inject loggers in construction for dl_tb_process due to very weird static assertions in the std::vector code being the type not constructible which is not true, so instead use the main MAC logger directly. * Replaced loggers in mac mux class. * Replaced loggers in mac pro_bsr. * Replaced loggers in mac proc phr. * Replaced loggers in mac proc SR and RA. * Replace loggers in mac UL HARQ. * Replaced loggers in main ue stack class. * Fixed nas test crashing due to a null string. * Ported mac_test to use the new loggers. * Removed TTI reporting for the PHY log as the old logger did. * Replaced loggers in UE phy tests. * Configure loggers in nas_test. * Replaced loggers in rrc_meas_test. * Replaced loggers in rrc_reconfig_test. * Added missing newline in tft_test. * Fix compilation errors in TTCN3 tests. * Fix linker error detected in CI and warning. * Replaced loggers in TTCN3 tests. * Fix a text replace error in some log messages. * Remove trailing newlines from log entries. * Remove old logger from rrc. * Flush backend before printing the test status. * - Fix compilation error from previous rebase. - Remove trailing newlines from some missing log entries.
4 years ago
srsue::ue ue(*log_sink);
if (ue.init(args, &log_wrapper)) {
ue.stop();
return SRSLTE_SUCCESS;
}
srslte::metrics_hub<ue_metrics_t> metricshub;
metrics_stdout _metrics_screen;
metrics_screen = &_metrics_screen;
metricshub.init(&ue, args.general.metrics_period_secs);
metricshub.add_listener(metrics_screen);
metrics_screen->set_ue_handle(&ue);
metrics_csv metrics_file(args.general.metrics_csv_filename, args.general.metrics_csv_append);
if (args.general.metrics_csv_enable) {
metricshub.add_listener(&metrics_file);
metrics_file.set_ue_handle(&ue);
if (args.general.metrics_csv_flush_period_sec > 0) {
metrics_file.set_flush_period((uint32_t)args.general.metrics_csv_flush_period_sec);
}
}
pthread_t input;
pthread_create(&input, nullptr, &input_loop, &args);
cout << "Attaching UE..." << endl;
ue.switch_on();
if (args.gui.enable) {
ue.start_plot();
}
while (running) {
sleep(1);
}
ue.switch_off();
pthread_cancel(input);
pthread_join(input, nullptr);
metricshub.stop();
metrics_file.stop();
ue.stop();
cout << "--- exiting ---" << endl;
return SRSLTE_SUCCESS;
}