mirror of https://github.com/pvnis/srsRAN_4G.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 changemaster
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
|
@ -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));
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue