mirror of https://github.com/PentHertz/srsLTE.git
Backport some changes from FAPI branch (#2124)
* Reorder DCI FORMAT enum * Fix endianness issue * Fix return codes in phy_ue_db * Log members should be destructed after the layers. * Add JSON metrics and Events. Add Alarm log channel. Simplify MAC metrics struct. * Restore metrics_stdout change
This commit is contained in:
parent
ea36e46635
commit
0498439d41
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSENB_ENB_EVENTS_H
|
||||
#define SRSENB_ENB_EVENTS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace srslog {
|
||||
class log_channel;
|
||||
}
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/// This interface logs different kinds of events to the configured channel. By default, if no log channel is configured
|
||||
/// logging will be disabled.
|
||||
class event_logger_interface
|
||||
{
|
||||
public:
|
||||
virtual ~event_logger_interface() = default;
|
||||
|
||||
/// Logs into the underlying log channel the RRC connected event.
|
||||
virtual void log_rrc_connected(unsigned cause) = 0;
|
||||
|
||||
/// Logs into the underlying log channel the RRC disconnected event.
|
||||
virtual void log_rrc_disconnect(unsigned reason) = 0;
|
||||
|
||||
/// Logs into the underlying log channel the S1 context create event.
|
||||
virtual void log_s1_ctx_create(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
|
||||
|
||||
/// Logs into the underlying log channel the S1 context delete event.
|
||||
virtual void log_s1_ctx_delete(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
|
||||
|
||||
/// Logs into the underlying log channel the when a sector has been started.
|
||||
virtual void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
|
||||
|
||||
/// Logs into the underlying log channel the when a sector has been stopped.
|
||||
virtual void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
|
||||
};
|
||||
|
||||
/// Singleton class to provide global access to the event_logger_interface interface.
|
||||
class event_logger
|
||||
{
|
||||
event_logger() = default;
|
||||
|
||||
public:
|
||||
/// Returns the instance of the event logger.
|
||||
static event_logger_interface& get();
|
||||
|
||||
/// Uses the specified log channel for event logging.
|
||||
/// NOTE: This method is not thread safe.
|
||||
static void configure(srslog::log_channel& c);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<event_logger_interface> pimpl;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSENB_ENB_EVENTS_H
|
|
@ -284,8 +284,8 @@ typedef enum {
|
|||
SRSLTE_DCI_FORMAT0 = 0,
|
||||
SRSLTE_DCI_FORMAT1,
|
||||
SRSLTE_DCI_FORMAT1A,
|
||||
SRSLTE_DCI_FORMAT1C,
|
||||
SRSLTE_DCI_FORMAT1B,
|
||||
SRSLTE_DCI_FORMAT1C,
|
||||
SRSLTE_DCI_FORMAT1D,
|
||||
SRSLTE_DCI_FORMAT2,
|
||||
SRSLTE_DCI_FORMAT2A,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
set(SOURCES arch_select.cc
|
||||
enb_events.cc
|
||||
backtrace.c
|
||||
buffer_pool.cc
|
||||
crash_handler.c
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
*
|
||||
* \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/enb_events.h"
|
||||
#include "srslte/srslog/context.h"
|
||||
#include "srslte/srslog/log_channel.h"
|
||||
|
||||
using namespace srsenb;
|
||||
|
||||
namespace {
|
||||
|
||||
/// Null object implementation that is used when no log channel is configured.
|
||||
class null_event_logger : public event_logger_interface
|
||||
{
|
||||
public:
|
||||
void log_rrc_connected(unsigned cause) override {}
|
||||
void log_rrc_disconnect(unsigned reason) override {}
|
||||
void log_s1_ctx_create(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override {}
|
||||
void log_s1_ctx_delete(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override {}
|
||||
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override {}
|
||||
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
/// Common metrics to all events.
|
||||
DECLARE_METRIC("type", metric_type_tag, std::string, "");
|
||||
DECLARE_METRIC("event_name", metric_event_name, std::string, "");
|
||||
|
||||
/// Context for sector start/stop.
|
||||
DECLARE_METRIC("pci", metric_pci, uint32_t, "");
|
||||
DECLARE_METRIC("cell_identity", metric_cell_identity, uint32_t, "");
|
||||
DECLARE_METRIC("sector_id", metric_sector_id, uint32_t, "");
|
||||
DECLARE_METRIC_SET("event_data", mset_sector_event, metric_pci, metric_cell_identity, metric_sector_id);
|
||||
using sector_event_t = srslog::build_context_type<metric_type_tag, metric_event_name, mset_sector_event>;
|
||||
|
||||
/// Context for RRC connect/disconnect.
|
||||
DECLARE_METRIC("cause", metric_cause, uint32_t, "");
|
||||
DECLARE_METRIC_SET("event_data", mset_rrc_event, metric_cause);
|
||||
using rrc_event_t = srslog::build_context_type<metric_type_tag, metric_event_name, mset_rrc_event>;
|
||||
|
||||
/// Context for S1 context create/delete.
|
||||
DECLARE_METRIC("mme_ue_s1ap_id", metric_ue_mme_id, uint32_t, "");
|
||||
DECLARE_METRIC("enb_ue_s1ap_id", metric_ue_enb_id, uint32_t, "");
|
||||
DECLARE_METRIC("rnti", metric_rnti, uint16_t, "");
|
||||
DECLARE_METRIC_SET("event_data", mset_s1apctx_event, metric_ue_mme_id, metric_ue_enb_id, metric_rnti);
|
||||
using s1apctx_event_t = srslog::build_context_type<metric_type_tag, metric_event_name, mset_s1apctx_event>;
|
||||
|
||||
/// Logs events into the configured log channel.
|
||||
class logging_event_logger : public event_logger_interface
|
||||
{
|
||||
public:
|
||||
explicit logging_event_logger(srslog::log_channel& c) : event_channel(c) {}
|
||||
|
||||
void log_rrc_connected(unsigned cause) override
|
||||
{
|
||||
rrc_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("rrc_connect");
|
||||
ctx.get<mset_rrc_event>().write<metric_cause>(cause);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
void log_rrc_disconnect(unsigned reason) override
|
||||
{
|
||||
rrc_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("rrc_disconnect");
|
||||
ctx.get<mset_rrc_event>().write<metric_cause>(reason);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
void log_s1_ctx_create(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override
|
||||
{
|
||||
s1apctx_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("s1_context_create");
|
||||
ctx.get<mset_s1apctx_event>().write<metric_ue_mme_id>(mme_id);
|
||||
ctx.get<mset_s1apctx_event>().write<metric_ue_enb_id>(enb_id);
|
||||
ctx.get<mset_s1apctx_event>().write<metric_rnti>(rnti);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
void log_s1_ctx_delete(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override
|
||||
{
|
||||
s1apctx_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("s1_context_delete");
|
||||
ctx.get<mset_s1apctx_event>().write<metric_ue_mme_id>(mme_id);
|
||||
ctx.get<mset_s1apctx_event>().write<metric_ue_enb_id>(enb_id);
|
||||
ctx.get<mset_s1apctx_event>().write<metric_rnti>(rnti);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override
|
||||
{
|
||||
sector_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("sector_start");
|
||||
ctx.get<mset_sector_event>().write<metric_pci>(pci);
|
||||
ctx.get<mset_sector_event>().write<metric_cell_identity>(cell_id);
|
||||
ctx.get<mset_sector_event>().write<metric_sector_id>(cc_idx);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override
|
||||
{
|
||||
sector_event_t ctx("");
|
||||
|
||||
ctx.write<metric_type_tag>("event");
|
||||
ctx.write<metric_event_name>("sector_stop");
|
||||
ctx.get<mset_sector_event>().write<metric_pci>(pci);
|
||||
ctx.get<mset_sector_event>().write<metric_cell_identity>(cell_id);
|
||||
ctx.get<mset_sector_event>().write<metric_sector_id>(cc_idx);
|
||||
event_channel(ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
srslog::log_channel& event_channel;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<event_logger_interface> event_logger::pimpl = std::unique_ptr<null_event_logger>(new null_event_logger);
|
||||
|
||||
event_logger_interface& event_logger::get()
|
||||
{
|
||||
return *pimpl;
|
||||
}
|
||||
|
||||
void event_logger::configure(srslog::log_channel& c)
|
||||
{
|
||||
pimpl = std::unique_ptr<logging_event_logger>(new logging_event_logger(c));
|
||||
}
|
|
@ -565,13 +565,13 @@ bool sch_subh::is_var_len_ce()
|
|||
|
||||
uint16_t sch_subh::get_c_rnti()
|
||||
{
|
||||
return (uint16_t)payload[0] << 8 | payload[1];
|
||||
return le16toh((uint16_t)payload[0] << 8 | payload[1]);
|
||||
}
|
||||
|
||||
uint64_t sch_subh::get_con_res_id()
|
||||
{
|
||||
return ((uint64_t)payload[5]) | (((uint64_t)payload[4]) << 8) | (((uint64_t)payload[3]) << 16) |
|
||||
(((uint64_t)payload[2]) << 24) | (((uint64_t)payload[1]) << 32) | (((uint64_t)payload[0]) << 40);
|
||||
return le64toh(((uint64_t)payload[5]) | (((uint64_t)payload[4]) << 8) | (((uint64_t)payload[3]) << 16) |
|
||||
(((uint64_t)payload[2]) << 24) | (((uint64_t)payload[1]) << 32) | (((uint64_t)payload[0]) << 40));
|
||||
}
|
||||
|
||||
float sch_subh::get_phr()
|
||||
|
@ -711,6 +711,7 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], ul_sch_lcid format)
|
|||
|
||||
bool sch_subh::set_c_rnti(uint16_t crnti)
|
||||
{
|
||||
crnti = htole32(crnti);
|
||||
if (((sch_pdu*)parent)->has_space_ce(2)) {
|
||||
w_payload_ce[0] = (uint8_t)((crnti & 0xff00) >> 8);
|
||||
w_payload_ce[1] = (uint8_t)((crnti & 0x00ff));
|
||||
|
@ -724,6 +725,7 @@ bool sch_subh::set_c_rnti(uint16_t crnti)
|
|||
}
|
||||
bool sch_subh::set_con_res_id(uint64_t con_res_id)
|
||||
{
|
||||
con_res_id = htole64(con_res_id);
|
||||
if (((sch_pdu*)parent)->has_space_ce(6)) {
|
||||
w_payload_ce[0] = (uint8_t)((con_res_id & 0xff0000000000) >> 40);
|
||||
w_payload_ce[1] = (uint8_t)((con_res_id & 0x00ff00000000) >> 32);
|
||||
|
|
|
@ -294,6 +294,10 @@ enable = false
|
|||
#metrics_period_secs = 1
|
||||
#metrics_csv_enable = false
|
||||
#metrics_csv_filename = /tmp/enb_metrics.csv
|
||||
#report_json_enable = true
|
||||
#report_json_filename = /tmp/enb_report.json
|
||||
#alarms_log_enable = true
|
||||
#alarms_filename = /tmp/enb_alarms.log
|
||||
#pregenerate_signals = false
|
||||
#tx_amplitude = 0.6
|
||||
#rrc_inactivity_timer = 30000
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "srsenb/hdr/phy/enb_phy_base.h"
|
||||
#include "srsenb/hdr/stack/enb_stack_base.h"
|
||||
#include "srsenb/hdr/stack/rrc/rrc_config.h"
|
||||
|
||||
#include "srslte/common/bcd_helpers.h"
|
||||
#include "srslte/common/buffer_pool.h"
|
||||
|
@ -81,6 +82,10 @@ struct general_args_t {
|
|||
float metrics_period_secs;
|
||||
bool metrics_csv_enable;
|
||||
std::string metrics_csv_filename;
|
||||
bool report_json_enable;
|
||||
std::string report_json_filename;
|
||||
bool alarms_log_enable;
|
||||
std::string alarms_filename;
|
||||
bool print_buffer_state;
|
||||
std::string eia_pref_list;
|
||||
std::string eea_pref_list;
|
||||
|
@ -129,11 +134,6 @@ private:
|
|||
|
||||
int parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg);
|
||||
|
||||
// eNB components
|
||||
std::unique_ptr<enb_stack_base> stack;
|
||||
std::unique_ptr<srslte::radio_base> radio;
|
||||
std::unique_ptr<enb_phy_base> phy;
|
||||
|
||||
srslte::logger* logger = nullptr;
|
||||
srslte::log_ref log; // Own logger for eNB
|
||||
|
||||
|
@ -145,6 +145,12 @@ private:
|
|||
bool started = false;
|
||||
|
||||
phy_cfg_t phy_cfg = {};
|
||||
rrc_cfg_t rrc_cfg = {};
|
||||
|
||||
// eNB components
|
||||
std::unique_ptr<enb_stack_base> stack = nullptr;
|
||||
std::unique_ptr<srslte::radio_base> radio = nullptr;
|
||||
std::unique_ptr<enb_phy_base> phy = nullptr;
|
||||
|
||||
srslte::LOG_LEVEL_ENUM level(std::string l);
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* File: metrics_json.h
|
||||
* Description: Metrics class printing to a json file.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SRSENB_METRICS_JSON_H
|
||||
#define SRSENB_METRICS_JSON_H
|
||||
|
||||
#include "srslte/interfaces/enb_metrics_interface.h"
|
||||
#include "srslte/srslog/log_channel.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
class metrics_json : public srslte::metrics_listener<enb_metrics_t>
|
||||
{
|
||||
public:
|
||||
metrics_json(srslog::log_channel& c) : log_c(c) {}
|
||||
|
||||
void set_metrics(const enb_metrics_t& m, const uint32_t period_usec) override;
|
||||
void set_handle(enb_metrics_interface* enb_);
|
||||
void stop() override {}
|
||||
|
||||
private:
|
||||
srslog::log_channel& log_c;
|
||||
enb_metrics_interface* enb;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSENB_METRICS_JSON_H
|
|
@ -283,6 +283,14 @@ public:
|
|||
*/
|
||||
bool is_pcell(uint16_t rnti, uint32_t enb_cc_idx) const;
|
||||
|
||||
/**
|
||||
* Asserts a given eNb cell is part of the given RNTI
|
||||
* @param rnti identifier of the UE
|
||||
* @param enb_cc_idx eNb cell/carrier index
|
||||
* @return It returns true if the cell is part of the UE, othwerwise it returns false
|
||||
*/
|
||||
bool ue_has_cell(uint16_t rnti, uint32_t enb_cc_idx) const;
|
||||
|
||||
/**
|
||||
* Get the current down-link physical layer configuration for an RNTI and an eNb cell/carrier
|
||||
*
|
||||
|
@ -330,7 +338,7 @@ public:
|
|||
* @param dci carries the Transport Block and required scheduling information
|
||||
*
|
||||
*/
|
||||
void set_ack_pending(uint32_t tti, uint32_t enb_cc_idx, const srslte_dci_dl_t& dci);
|
||||
bool set_ack_pending(uint32_t tti, uint32_t enb_cc_idx, const srslte_dci_dl_t& dci);
|
||||
|
||||
/**
|
||||
* Fills the Uplink Control Information (UCI) configuration and returns true/false idicating if UCI bits are required.
|
||||
|
@ -339,14 +347,14 @@ public:
|
|||
* @param rnti is the UE identifier
|
||||
* @param aperiodic_cqi_request indicates if aperiodic CQI was requested
|
||||
* @param uci_cfg brings the UCI configuration
|
||||
* @return true if UCI decoding is required and false otherwise
|
||||
* @return 1 if UCI decoding is required, 0 if not, -1 if error
|
||||
*/
|
||||
bool fill_uci_cfg(uint32_t tti,
|
||||
uint32_t enb_cc_idx,
|
||||
uint16_t rnti,
|
||||
bool aperiodic_cqi_request,
|
||||
bool is_pusch_available,
|
||||
srslte_uci_cfg_t& uci_cfg);
|
||||
int fill_uci_cfg(uint32_t tti,
|
||||
uint32_t enb_cc_idx,
|
||||
uint16_t rnti,
|
||||
bool aperiodic_cqi_request,
|
||||
bool is_pusch_available,
|
||||
srslte_uci_cfg_t& uci_cfg);
|
||||
|
||||
/**
|
||||
* Sends the decoded Uplink Control Information by PUCCH or PUSCH to MAC
|
||||
|
|
|
@ -23,7 +23,7 @@ endif (RPATH)
|
|||
add_library(enb_cfg_parser STATIC parser.cc enb_cfg_parser.cc)
|
||||
target_link_libraries(enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
|
||||
|
||||
add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc)
|
||||
add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc)
|
||||
|
||||
set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_upper srsenb_mac srsenb_rrc srslog)
|
||||
set(SRSLTE_SOURCES srslte_common srslte_mac srslte_phy srslte_upper srslte_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "srsenb/hdr/stack/enb_stack_lte.h"
|
||||
#include "srsenb/src/enb_cfg_parser.h"
|
||||
#include "srslte/build_info.h"
|
||||
#include "srslte/common/enb_events.h"
|
||||
#include "srslte/radio/radio_null.h"
|
||||
#ifdef HAVE_5GNR
|
||||
#include "srsenb/hdr/phy/vnf_phy_nr.h"
|
||||
|
@ -46,7 +47,6 @@ int enb::init(const all_args_t& args_, srslte::logger* logger_)
|
|||
log->info("%s", get_build_string().c_str());
|
||||
|
||||
// Validate arguments
|
||||
rrc_cfg_t rrc_cfg = {};
|
||||
if (parse_args(args_, rrc_cfg)) {
|
||||
srslte::console("Error processing arguments.\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -145,6 +145,11 @@ int enb::init(const all_args_t& args_, srslte::logger* logger_)
|
|||
|
||||
started = true; // set to true in any case to allow stopping the eNB if an error happened
|
||||
|
||||
// Now that everything is setup, log sector start events.
|
||||
for (unsigned i = 0, e = rrc_cfg.cell_list.size(); i != e; ++i) {
|
||||
event_logger::get().log_sector_start(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id);
|
||||
}
|
||||
|
||||
if (ret == SRSLTE_SUCCESS) {
|
||||
srslte::console("\n==== eNodeB started ===\n");
|
||||
srslte::console("Type <t> to view trace\n");
|
||||
|
@ -152,6 +157,7 @@ int enb::init(const all_args_t& args_, srslte::logger* logger_)
|
|||
// if any of the layers failed to start, make sure the rest is stopped in a controlled manner
|
||||
stop();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -171,15 +177,20 @@ void enb::stop()
|
|||
radio->stop();
|
||||
}
|
||||
|
||||
// Now that everything is teared down, log sector stop events.
|
||||
for (unsigned i = 0, e = rrc_cfg.cell_list.size(); i != e; ++i) {
|
||||
event_logger::get().log_sector_stop(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id);
|
||||
}
|
||||
|
||||
started = false;
|
||||
}
|
||||
}
|
||||
|
||||
int enb::parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg)
|
||||
int enb::parse_args(const all_args_t& args_, rrc_cfg_t& _rrc_cfg)
|
||||
{
|
||||
// set member variable
|
||||
args = args_;
|
||||
return enb_conf_sections::parse_cfg_files(&args, &rrc_cfg, &phy_cfg);
|
||||
return enb_conf_sections::parse_cfg_files(&args, &_rrc_cfg, &phy_cfg);
|
||||
}
|
||||
|
||||
void enb::start_plot()
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
|
||||
#include "srsenb/hdr/enb.h"
|
||||
#include "srsenb/hdr/metrics_csv.h"
|
||||
#include "srsenb/hdr/metrics_json.h"
|
||||
#include "srsenb/hdr/metrics_stdout.h"
|
||||
#include "srslte/common/enb_events.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace srsenb;
|
||||
|
@ -191,6 +193,10 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("expert.equalizer_mode", bpo::value<string>(&args->phy.equalizer_mode)->default_value("mmse"), "Equalizer mode")
|
||||
("expert.estimator_fil_w", bpo::value<float>(&args->phy.estimator_fil_w)->default_value(0.1), "Chooses the coefficients for the 3-tap channel estimator centered filter.")
|
||||
("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.")
|
||||
("expert.report_json_enable", bpo::value<bool>(&args->general.report_json_enable)->default_value(true), "Write eNB report to JSON file")
|
||||
("expert.report_json_filename", bpo::value<string>(&args->general.report_json_filename)->default_value("/tmp/enb_report.json"), "Report JSON filename")
|
||||
("expert.alarms_log_enable", bpo::value<bool>(&args->general.alarms_log_enable)->default_value(true), "Log alarms")
|
||||
("expert.alarms_filename", bpo::value<string>(&args->general.alarms_filename)->default_value("/tmp/enb_alarms.log"), "Alarms filename")
|
||||
("expert.rrc_inactivity_timer", bpo::value<uint32_t>(&args->general.rrc_inactivity_timer)->default_value(30000), "Inactivity timer in ms.")
|
||||
("expert.print_buffer_state", bpo::value<bool>(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds")
|
||||
("expert.eea_pref_list", bpo::value<string>(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).")
|
||||
|
@ -478,6 +484,11 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
srslte::srslog_wrapper log_wrapper(*chan);
|
||||
|
||||
// Alarms log channel creation.
|
||||
srslog::sink& alarm_sink = srslog::fetch_file_sink(args.general.alarms_filename);
|
||||
srslog::log_channel& alarms_channel = srslog::fetch_log_channel("alarms", alarm_sink, {"ALRM", '\0', false});
|
||||
alarms_channel.set_enabled(args.general.alarms_log_enable);
|
||||
|
||||
// Start the log backend.
|
||||
srslog::init();
|
||||
|
||||
|
@ -487,6 +498,17 @@ int main(int argc, char* argv[])
|
|||
|
||||
srslte::check_scaling_governor(args.rf.device_name);
|
||||
|
||||
// Set up the JSON log channel used by metrics and events.
|
||||
srslog::sink& json_sink =
|
||||
srslog::fetch_file_sink(args.general.report_json_filename, 0, srslog::create_json_formatter());
|
||||
srslog::log_channel& json_channel = srslog::fetch_log_channel("JSON_channel", json_sink, {});
|
||||
json_channel.set_enabled(args.general.report_json_enable);
|
||||
|
||||
// Configure the event logger just before starting the eNB class.
|
||||
if (args.general.report_json_enable) {
|
||||
event_logger::configure(json_channel);
|
||||
}
|
||||
|
||||
// Create eNB
|
||||
unique_ptr<srsenb::enb> enb{new srsenb::enb};
|
||||
if (enb->init(args, &log_wrapper) != SRSLTE_SUCCESS) {
|
||||
|
@ -505,6 +527,12 @@ int main(int argc, char* argv[])
|
|||
metrics_file.set_handle(enb.get());
|
||||
}
|
||||
|
||||
srsenb::metrics_json json_metrics(json_channel);
|
||||
if (args.general.report_json_enable) {
|
||||
metricshub.add_listener(&json_metrics);
|
||||
json_metrics.set_handle(enb.get());
|
||||
}
|
||||
|
||||
// create input thread
|
||||
std::thread input(&input_loop, &metrics_screen, (enb_command_interface*)enb.get());
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
*
|
||||
* \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 "srsenb/hdr/metrics_json.h"
|
||||
#include "srslte/srslog/context.h"
|
||||
|
||||
using namespace srsenb;
|
||||
|
||||
void metrics_json::set_handle(enb_metrics_interface* enb_)
|
||||
{
|
||||
enb = enb_;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Bearer container metrics.
|
||||
DECLARE_METRIC("bearer_id", metric_bearer_id, uint32_t, "");
|
||||
DECLARE_METRIC("qci", metric_qci, uint32_t, "");
|
||||
DECLARE_METRIC_SET("bearer_container", mset_bearer_container, metric_bearer_id, metric_qci);
|
||||
|
||||
/// UE container metrics.
|
||||
DECLARE_METRIC("ue_rnti", metric_ue_rnti, uint32_t, "");
|
||||
DECLARE_METRIC("dl_cqi", metric_dl_cqi, float, "");
|
||||
DECLARE_METRIC("dl_mcs", metric_dl_mcs, float, "");
|
||||
DECLARE_METRIC("dl_bitrate", metric_dl_bitrate, float, "");
|
||||
DECLARE_METRIC("dl_bler", metric_dl_bler, float, "");
|
||||
DECLARE_METRIC("ul_snr", metric_ul_snr, float, "");
|
||||
DECLARE_METRIC("ul_mcs", metric_ul_mcs, float, "");
|
||||
DECLARE_METRIC("ul_bitrate", metric_ul_bitrate, float, "");
|
||||
DECLARE_METRIC("ul_bler", metric_ul_bler, float, "");
|
||||
DECLARE_METRIC("ul_phr", metric_ul_phr, float, "");
|
||||
DECLARE_METRIC("bsr", metric_bsr, int, "");
|
||||
DECLARE_METRIC_LIST("bearer_list", mlist_bearers, std::vector<mset_bearer_container>);
|
||||
DECLARE_METRIC_SET("ue_container",
|
||||
mset_ue_container,
|
||||
metric_ue_rnti,
|
||||
metric_dl_cqi,
|
||||
metric_dl_mcs,
|
||||
metric_dl_bitrate,
|
||||
metric_dl_bler,
|
||||
metric_ul_snr,
|
||||
metric_ul_mcs,
|
||||
metric_ul_bitrate,
|
||||
metric_ul_bler,
|
||||
metric_ul_phr,
|
||||
metric_bsr,
|
||||
mlist_bearers);
|
||||
|
||||
/// Sector container metrics.
|
||||
DECLARE_METRIC("sector_id", metric_sector_id, uint32_t, "");
|
||||
DECLARE_METRIC("sector_rach", metric_sector_rach, uint32_t, "");
|
||||
DECLARE_METRIC_LIST("ue_list", mlist_ues, std::vector<mset_ue_container>);
|
||||
DECLARE_METRIC_SET("sector_container", mset_sector_container, metric_sector_id, metric_sector_rach, mlist_ues);
|
||||
|
||||
/// Metrics root object.
|
||||
DECLARE_METRIC("type", metric_type_tag, std::string, "");
|
||||
DECLARE_METRIC_LIST("sector_list", mlist_sector, std::vector<mset_sector_container>);
|
||||
|
||||
/// Metrics context.
|
||||
using metric_context_t = srslog::build_context_type<metric_type_tag, mlist_sector>;
|
||||
|
||||
} // namespace
|
||||
|
||||
/// Fill the metrics for the i'th UE in the enb metrics struct.
|
||||
static void fill_ue_metrics(mset_ue_container& ue, const enb_metrics_t& m, unsigned i)
|
||||
{
|
||||
ue.write<metric_ue_rnti>(m.stack.mac.ues[i].rnti);
|
||||
ue.write<metric_dl_cqi>(std::max(0.1f, m.stack.mac.ues[i].dl_cqi));
|
||||
if (!std::isnan(m.phy[i].dl.mcs)) {
|
||||
ue.write<metric_dl_mcs>(std::max(0.1f, m.phy[i].dl.mcs));
|
||||
}
|
||||
if (m.stack.mac.ues[i].tx_brate > 0) {
|
||||
ue.write<metric_dl_bitrate>(
|
||||
std::max(0.1f, (float)m.stack.mac.ues[i].tx_brate / (m.stack.mac.ues[i].nof_tti * 0.001f)));
|
||||
}
|
||||
if (m.stack.mac.ues[i].tx_pkts > 0 && m.stack.mac.ues[i].tx_errors > 0) {
|
||||
ue.write<metric_dl_bler>(std::max(0.1f, (float)100 * m.stack.mac.ues[i].tx_errors / m.stack.mac.ues[i].tx_pkts));
|
||||
}
|
||||
if (!std::isnan(m.phy[i].ul.sinr)) {
|
||||
ue.write<metric_ul_snr>(std::max(0.1f, m.phy[i].ul.sinr));
|
||||
}
|
||||
if (!std::isnan(m.phy[i].ul.mcs)) {
|
||||
ue.write<metric_ul_mcs>(std::max(0.1f, m.phy[i].ul.mcs));
|
||||
}
|
||||
if (m.stack.mac.ues[i].rx_brate > 0) {
|
||||
ue.write<metric_ul_bitrate>(
|
||||
std::max(0.1f, (float)m.stack.mac.ues[i].rx_brate / (m.stack.mac.ues[i].nof_tti * 0.001f)));
|
||||
}
|
||||
if (m.stack.mac.ues[i].rx_pkts > 0 && m.stack.mac.ues[i].rx_errors > 0) {
|
||||
ue.write<metric_ul_bler>(std::max(0.1f, (float)100 * m.stack.mac.ues[i].rx_errors / m.stack.mac.ues[i].rx_pkts));
|
||||
}
|
||||
ue.write<metric_ul_phr>(m.stack.mac.ues[i].phr);
|
||||
ue.write<metric_bsr>(m.stack.mac.ues[i].ul_buffer);
|
||||
|
||||
// For each data bearer of this UE...
|
||||
auto& bearer_list = ue.get<mlist_bearers>();
|
||||
for (const auto& drb : m.stack.rrc.ues[i].drb_qci_map) {
|
||||
bearer_list.emplace_back();
|
||||
auto& bearer_container = bearer_list.back();
|
||||
bearer_container.write<metric_bearer_id>(drb.first);
|
||||
bearer_container.write<metric_qci>(drb.second);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns false if the input index is out of bounds in the metrics struct.
|
||||
static bool has_valid_metric_ranges(const enb_metrics_t& m, unsigned index)
|
||||
{
|
||||
if (index >= m.phy.size()) {
|
||||
return false;
|
||||
}
|
||||
if (index >= m.stack.mac.ues.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void metrics_json::set_metrics(const enb_metrics_t& m, const uint32_t period_usec)
|
||||
{
|
||||
if (!enb) {
|
||||
return;
|
||||
}
|
||||
if (m.stack.mac.cc_rach_counter.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
metric_context_t ctx("JSON Metrics");
|
||||
|
||||
// Fill root object.
|
||||
ctx.write<metric_type_tag>("metrics");
|
||||
auto& sector_list = ctx.get<mlist_sector>();
|
||||
sector_list.resize(m.stack.mac.cc_rach_counter.size());
|
||||
|
||||
// For each sector...
|
||||
for (unsigned cc_idx = 0, e = sector_list.size(); cc_idx != e; ++cc_idx) {
|
||||
auto& sector = sector_list[cc_idx];
|
||||
sector.write<metric_sector_id>(cc_idx);
|
||||
sector.write<metric_sector_rach>(m.stack.mac.cc_rach_counter[cc_idx]);
|
||||
|
||||
// For each UE in this sector...
|
||||
for (unsigned i = 0; i != m.stack.rrc.ues.size(); ++i) {
|
||||
if (!has_valid_metric_ranges(m, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only record UEs that belong to this sector.
|
||||
if (m.stack.mac.ues[i].cc_idx != cc_idx) {
|
||||
continue;
|
||||
}
|
||||
sector.get<mlist_ues>().emplace_back();
|
||||
fill_ue_metrics(sector.get<mlist_ues>().back(), m, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Log the context.
|
||||
log_c(ctx);
|
||||
}
|
|
@ -390,6 +390,11 @@ void phy_ue_db::activate_deactivate_scell(uint16_t rnti, uint32_t ue_cc_idx, boo
|
|||
cell_info.state = (activate) ? cell_state_secondary_active : cell_state_secondary_inactive;
|
||||
}
|
||||
|
||||
bool phy_ue_db::ue_has_cell(uint16_t rnti, uint32_t enb_cc_idx) const
|
||||
{
|
||||
return _assert_enb_cc(rnti, enb_cc_idx) == SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
bool phy_ue_db::is_pcell(uint16_t rnti, uint32_t enb_cc_idx) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
@ -440,16 +445,16 @@ srslte_dci_cfg_t phy_ue_db::get_dci_ul_config(uint16_t rnti, uint32_t enb_cc_idx
|
|||
return _get_rnti_config(rnti, enb_cc_idx).dl_cfg.dci;
|
||||
}
|
||||
|
||||
void phy_ue_db::set_ack_pending(uint32_t tti, uint32_t enb_cc_idx, const srslte_dci_dl_t& dci)
|
||||
bool phy_ue_db::set_ack_pending(uint32_t tti, uint32_t enb_cc_idx, const srslte_dci_dl_t& dci)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
// Assert rnti and cell exits and it is active
|
||||
if (_assert_active_enb_cc(dci.rnti, enb_cc_idx) != SRSLTE_SUCCESS) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
common_ue& ue = ue_db[dci.rnti];
|
||||
common_ue& ue = ue_db.at(dci.rnti);
|
||||
uint32_t ue_cc_idx = _get_ue_cc_idx(dci.rnti, enb_cc_idx);
|
||||
|
||||
srslte_pdsch_ack_cc_t& pdsch_ack_cc = ue.pdsch_ack[tti].cc[ue_cc_idx];
|
||||
|
@ -473,14 +478,15 @@ void phy_ue_db::set_ack_pending(uint32_t tti, uint32_t enb_cc_idx, const srslte_
|
|||
pdsch_ack_m.value[tb_idx] = 2;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool phy_ue_db::fill_uci_cfg(uint32_t tti,
|
||||
uint32_t enb_cc_idx,
|
||||
uint16_t rnti,
|
||||
bool aperiodic_cqi_request,
|
||||
bool is_pusch_available,
|
||||
srslte_uci_cfg_t& uci_cfg)
|
||||
int phy_ue_db::fill_uci_cfg(uint32_t tti,
|
||||
uint32_t enb_cc_idx,
|
||||
uint16_t rnti,
|
||||
bool aperiodic_cqi_request,
|
||||
bool is_pusch_available,
|
||||
srslte_uci_cfg_t& uci_cfg)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
|
@ -489,12 +495,12 @@ bool phy_ue_db::fill_uci_cfg(uint32_t tti,
|
|||
|
||||
// Assert Cell List configuration
|
||||
if (_assert_cell_list_cfg() != SRSLTE_SUCCESS) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Assert eNb Cell/Carrier for the given RNTI
|
||||
if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSLTE_SUCCESS) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the eNb cell/carrier index with lowest serving cell index (ue_cc_idx) that has an available grant.
|
||||
|
@ -503,17 +509,17 @@ bool phy_ue_db::fill_uci_cfg(uint32_t tti,
|
|||
|
||||
// There is a PUSCH grant available for the provided RNTI in at least one serving cell and this call is for PUCCH
|
||||
if (pusch_grant_available and not is_pusch_available) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// There is a PUSCH grant and enb_cc_idx with lowest ue_cc_idx with a grant
|
||||
if (pusch_grant_available and uci_enb_cc_id != enb_cc_idx) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// No PUSCH grant for this TTI and cell and no enb_cc_idx is not the PCell
|
||||
if (not pusch_grant_available and _get_ue_cc_idx(rnti, enb_cc_idx) != 0) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
common_ue& ue = ue_db.at(rnti);
|
||||
|
@ -564,7 +570,7 @@ bool phy_ue_db::fill_uci_cfg(uint32_t tti,
|
|||
uci_required |= (srslte_uci_cfg_total_ack(&uci_cfg) > 0);
|
||||
|
||||
// Return whether UCI needs to be decoded
|
||||
return uci_required;
|
||||
return uci_required ? 1 : 0;
|
||||
}
|
||||
|
||||
void phy_ue_db::send_uci_data(uint32_t tti,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "srsenb/hdr/stack/rrc/rrc_mobility.h"
|
||||
#include "srsenb/hdr/stack/rrc/ue_rr_cfg.h"
|
||||
#include "srslte/asn1/rrc_utils.h"
|
||||
#include "srslte/common/enb_events.h"
|
||||
#include "srslte/common/int_helpers.h"
|
||||
|
||||
using namespace asn1::rrc;
|
||||
|
@ -305,6 +306,9 @@ void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsl
|
|||
parent->s1ap->initial_ue(rnti, s1ap_cause, std::move(pdu));
|
||||
}
|
||||
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
|
||||
|
||||
// Log event.
|
||||
event_logger::get().log_rrc_connected(static_cast<unsigned>(s1ap_cause.value));
|
||||
}
|
||||
|
||||
void rrc::ue::send_connection_reject()
|
||||
|
@ -642,6 +646,9 @@ void rrc::ue::send_connection_release()
|
|||
}
|
||||
|
||||
send_dl_dcch(&dl_dcch_msg);
|
||||
|
||||
// Log rrc release event.
|
||||
event_logger::get().log_rrc_disconnect(static_cast<unsigned>(rel_ies.release_cause));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "srsenb/hdr/stack/upper/common_enb.h"
|
||||
#include "srslte/adt/scope_exit.h"
|
||||
#include "srslte/common/bcd_helpers.h"
|
||||
#include "srslte/common/enb_events.h"
|
||||
#include "srslte/common/int_helpers.h"
|
||||
#include "srslte/common/logmap.h"
|
||||
|
||||
|
@ -1115,6 +1116,9 @@ bool s1ap::ue::send_uectxtreleasecomplete()
|
|||
container.enb_ue_s1ap_id.value = ctxt.enb_ue_s1ap_id;
|
||||
container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id;
|
||||
|
||||
// Log event.
|
||||
event_logger::get().log_s1_ctx_delete(ctxt.mme_ue_s1ap_id, ctxt.enb_ue_s1ap_id, ctxt.rnti);
|
||||
|
||||
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete");
|
||||
}
|
||||
|
||||
|
@ -1146,6 +1150,9 @@ bool s1ap::ue::send_initial_ctxt_setup_response(const asn1::s1ap::init_context_s
|
|||
}
|
||||
}
|
||||
|
||||
// Log event.
|
||||
event_logger::get().log_s1_ctx_create(ctxt.mme_ue_s1ap_id, ctxt.enb_ue_s1ap_id, ctxt.rnti);
|
||||
|
||||
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "InitialContextSetupResponse");
|
||||
}
|
||||
|
||||
|
|
|
@ -1288,7 +1288,7 @@ public:
|
|||
radio = unique_dummy_radio_t(
|
||||
new dummy_radio(args.nof_enb_cells * args.cell.nof_ports, args.cell.nof_prb, args.log_level));
|
||||
|
||||
/// Create Dummy Stack isntance
|
||||
/// Create Dummy Stack instance
|
||||
stack = unique_dummy_stack_t(new dummy_stack(phy_cfg, phy_rrc_cfg, args.log_level, args.rnti));
|
||||
stack->set_active_cell_list(args.ue_cell_list);
|
||||
|
||||
|
|
Loading…
Reference in New Issue