mirror of https://github.com/pvnis/srsRAN_4G.git
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.
440 lines
18 KiB
C++
440 lines
18 KiB
C++
/**
|
|
*
|
|
* \section COPYRIGHT
|
|
*
|
|
* Copyright 2013-2021 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 "srsran/common/enb_events.h"
|
|
#include "srsran/srslog/context.h"
|
|
#include "srsran/srslog/log_channel.h"
|
|
#include <mutex>
|
|
#include <unordered_map>
|
|
|
|
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_event(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
unsigned type,
|
|
unsigned additional_info,
|
|
uint16_t rnti) override
|
|
{}
|
|
void log_s1_ctx_create(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override {}
|
|
void log_s1_ctx_delete(uint32_t enb_cc_idx, 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, const std::string& hnb_name) override {}
|
|
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override {}
|
|
void log_measurement_report(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
uint16_t rnti) override
|
|
{}
|
|
void log_rlf_report(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
uint16_t rnti) override
|
|
{}
|
|
void log_rlf_detected(uint32_t enb_cc_idx, const std::string& type, uint16_t rnti) override {}
|
|
void log_handover_command(uint32_t enb_cc_idx,
|
|
uint32_t target_pci,
|
|
uint32_t target_earfcn,
|
|
uint16_t new_ue_rnti,
|
|
uint16_t rnti) override
|
|
{}
|
|
void log_connection_resume(uint32_t enb_cc_idx, uint16_t resume_rnti, uint16_t rnti) override {}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
/// Returns the current time in seconds with ms precision since UNIX epoch.
|
|
static double get_time_stamp()
|
|
{
|
|
auto tp = std::chrono::system_clock::now().time_since_epoch();
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(tp).count() * 1e-3;
|
|
}
|
|
|
|
/// Escapes the input string.
|
|
static std::string escape_string(const std::string& s)
|
|
{
|
|
fmt::memory_buffer buff;
|
|
for (auto c : s) {
|
|
switch (c) {
|
|
case ' ':
|
|
break;
|
|
case '"':
|
|
fmt::format_to(buff, "\\\"");
|
|
break;
|
|
case '\\':
|
|
fmt::format_to(buff, "\\\\");
|
|
break;
|
|
case '\b':
|
|
fmt::format_to(buff, "\\b");
|
|
break;
|
|
case '\f':
|
|
fmt::format_to(buff, "\\f");
|
|
break;
|
|
case '\n':
|
|
fmt::format_to(buff, "\\n");
|
|
break;
|
|
case '\r':
|
|
fmt::format_to(buff, "\\r");
|
|
break;
|
|
case '\t':
|
|
fmt::format_to(buff, "\\t");
|
|
break;
|
|
default:
|
|
// Cast to signed char for machines that treat chars as an unsigned type.
|
|
if ((signed char)c >= '\x00' && (signed char)c <= '\x1f') {
|
|
fmt::format_to(buff, "\\u{:04x}", c);
|
|
} else {
|
|
buff.push_back(c);
|
|
}
|
|
}
|
|
}
|
|
return fmt::to_string(buff);
|
|
}
|
|
|
|
namespace {
|
|
|
|
/// Common metrics to all events.
|
|
DECLARE_METRIC("type", metric_type_tag, std::string, "");
|
|
DECLARE_METRIC("timestamp", metric_timestamp_tag, double, "");
|
|
DECLARE_METRIC("carrier_id", metric_carrier_id, uint32_t, "");
|
|
DECLARE_METRIC("cell_id", metric_cell_id, uint32_t, "");
|
|
DECLARE_METRIC("event_name", metric_event_name, std::string, "");
|
|
|
|
DECLARE_METRIC("rnti", metric_rnti, uint16_t, "");
|
|
|
|
/// ASN1 message metrics.
|
|
DECLARE_METRIC("asn1_length", metric_asn1_length, uint32_t, "");
|
|
DECLARE_METRIC("asn1_message", metric_asn1_message, std::string, "");
|
|
|
|
/// Context for sector start/stop.
|
|
DECLARE_METRIC("pci", metric_pci, uint32_t, "");
|
|
DECLARE_METRIC("cell_identity", metric_cell_identity, std::string, "");
|
|
DECLARE_METRIC("sib9_home_enb_name", metric_sib9_home_enb_name, std::string, "");
|
|
DECLARE_METRIC_SET("event_data", mset_sector_event, metric_pci, metric_cell_identity, metric_sib9_home_enb_name);
|
|
using sector_event_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_sector_event>;
|
|
|
|
/// Context for a RRC event.
|
|
DECLARE_METRIC("asn1_type", metric_asn1_type, uint32_t, "");
|
|
DECLARE_METRIC("additional", metric_additional, uint32_t, "");
|
|
DECLARE_METRIC_SET("event_data",
|
|
mset_rrc_event,
|
|
metric_rnti,
|
|
metric_asn1_length,
|
|
metric_asn1_message,
|
|
metric_asn1_type,
|
|
metric_additional);
|
|
using rrc_event_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
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_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_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_s1apctx_event>;
|
|
|
|
/// Context for the RLF report event.
|
|
DECLARE_METRIC_SET("event_data", mset_rlf_report_event, metric_asn1_length, metric_asn1_message, metric_rnti);
|
|
using rlf_report_event_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_rlf_report_event>;
|
|
|
|
/// Context for measurement report.
|
|
DECLARE_METRIC_SET("event_data", mset_meas_report_event, metric_asn1_length, metric_asn1_message, metric_rnti);
|
|
using meas_report_event_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_meas_report_event>;
|
|
|
|
/// Context for the handover command event.
|
|
DECLARE_METRIC("target_pci", metric_target_pci, uint32_t, "");
|
|
DECLARE_METRIC("target_earfcn", metric_target_earfcn, uint32_t, "");
|
|
DECLARE_METRIC("new_ue_rnti", metric_new_ue_rnti, uint32_t, "");
|
|
DECLARE_METRIC_SET("event_data",
|
|
mset_ho_cmd_event,
|
|
metric_rnti,
|
|
metric_target_pci,
|
|
metric_target_earfcn,
|
|
metric_new_ue_rnti);
|
|
using ho_cmd_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_ho_cmd_event>;
|
|
|
|
/// Context for the connection resume event.
|
|
DECLARE_METRIC("resume_rnti", metric_resume_rnti, uint32_t, "");
|
|
DECLARE_METRIC_SET("event_data", mset_conn_resume_event, metric_rnti, metric_resume_rnti);
|
|
using conn_resume_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_conn_resume_event>;
|
|
|
|
/// Context for the RLF detected event.
|
|
DECLARE_METRIC("type", metric_rlf_type, std::string, "");
|
|
DECLARE_METRIC_SET("event_data", mset_rlf_detected_event, metric_rnti, metric_rlf_type);
|
|
using rlf_detected_t = srslog::build_context_type<metric_type_tag,
|
|
metric_timestamp_tag,
|
|
metric_carrier_id,
|
|
metric_cell_id,
|
|
metric_event_name,
|
|
mset_rlf_detected_event>;
|
|
|
|
/// Logs events into the configured log channel.
|
|
class logging_event_logger : public event_logger_interface
|
|
{
|
|
public:
|
|
logging_event_logger(srslog::log_channel& c, event_logger::asn1_output_format asn1_format) :
|
|
event_channel(c), asn1_format(asn1_format)
|
|
{}
|
|
|
|
void log_rrc_event(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
unsigned type,
|
|
unsigned additional_info,
|
|
uint16_t rnti) override
|
|
{
|
|
rrc_event_t ctx("");
|
|
|
|
const std::string& asn1 =
|
|
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("rrc_log");
|
|
ctx.get<mset_rrc_event>().write<metric_rnti>(rnti);
|
|
ctx.get<mset_rrc_event>().write<metric_asn1_length>(asn1.size());
|
|
ctx.get<mset_rrc_event>().write<metric_asn1_message>(asn1);
|
|
ctx.get<mset_rrc_event>().write<metric_asn1_type>(type);
|
|
ctx.get<mset_rrc_event>().write<metric_additional>(additional_info);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_s1_ctx_create(uint32_t enb_cc_idx, 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_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
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 enb_cc_idx, 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_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
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, const std::string& hnb_name) override
|
|
{
|
|
register_pci(cc_idx, pci);
|
|
|
|
sector_event_t ctx("");
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(cc_idx);
|
|
ctx.write<metric_cell_id>(pci);
|
|
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>(fmt::to_string(cell_id));
|
|
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>(hnb_name);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override
|
|
{
|
|
sector_event_t ctx("");
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(cc_idx));
|
|
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>(fmt::to_string(cell_id));
|
|
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>(hnb_name);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_measurement_report(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
uint16_t rnti) override
|
|
{
|
|
meas_report_event_t ctx("");
|
|
|
|
const std::string& asn1 =
|
|
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("measurement_report");
|
|
ctx.get<mset_meas_report_event>().write<metric_asn1_length>(asn1.size());
|
|
ctx.get<mset_meas_report_event>().write<metric_asn1_message>(asn1);
|
|
ctx.get<mset_meas_report_event>().write<metric_rnti>(rnti);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_rlf_report(uint32_t enb_cc_idx,
|
|
const std::string& asn1_oct_str,
|
|
const std::string& asn1_txt_str,
|
|
uint16_t rnti) override
|
|
{
|
|
rlf_report_event_t ctx("");
|
|
|
|
const std::string& asn1 =
|
|
(asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str);
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("rlf_report");
|
|
ctx.get<mset_rlf_report_event>().write<metric_asn1_length>(asn1.size());
|
|
ctx.get<mset_rlf_report_event>().write<metric_asn1_message>(asn1);
|
|
ctx.get<mset_rlf_report_event>().write<metric_rnti>(rnti);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_rlf_detected(uint32_t enb_cc_idx, const std::string& type, uint16_t rnti) override
|
|
{
|
|
rlf_detected_t ctx("");
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("rlf_detected");
|
|
ctx.get<mset_rlf_detected_event>().write<metric_rnti>(rnti);
|
|
ctx.get<mset_rlf_detected_event>().write<metric_rlf_type>(type);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_handover_command(uint32_t enb_cc_idx,
|
|
uint32_t target_pci,
|
|
uint32_t target_earfcn,
|
|
uint16_t new_ue_rnti,
|
|
uint16_t rnti) override
|
|
{
|
|
ho_cmd_t ctx("");
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("ho_command");
|
|
ctx.get<mset_ho_cmd_event>().write<metric_rnti>(rnti);
|
|
ctx.get<mset_ho_cmd_event>().write<metric_target_pci>(target_pci);
|
|
ctx.get<mset_ho_cmd_event>().write<metric_target_earfcn>(target_earfcn);
|
|
ctx.get<mset_ho_cmd_event>().write<metric_new_ue_rnti>(new_ue_rnti);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
void log_connection_resume(uint32_t enb_cc_idx, uint16_t resume_rnti, uint16_t rnti) override
|
|
{
|
|
conn_resume_t ctx("");
|
|
|
|
ctx.write<metric_type_tag>("event");
|
|
ctx.write<metric_timestamp_tag>(get_time_stamp());
|
|
ctx.write<metric_carrier_id>(enb_cc_idx);
|
|
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
|
|
ctx.write<metric_event_name>("connection_resume");
|
|
ctx.get<mset_conn_resume_event>().write<metric_rnti>(rnti);
|
|
ctx.get<mset_conn_resume_event>().write<metric_resume_rnti>(resume_rnti);
|
|
event_channel(ctx);
|
|
}
|
|
|
|
private:
|
|
/// Associates the corresponding cc_idx with its PCI.
|
|
void register_pci(uint32_t cc_idx, uint32_t pci)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m);
|
|
cc_idx_to_pci_map[cc_idx] = pci;
|
|
}
|
|
|
|
/// Returns the PCI value associated to specified cc_idx, otherwise returns an invalid PCI value if not previous
|
|
/// association has been set.
|
|
uint32_t get_pci(uint32_t cc_idx) const
|
|
{
|
|
std::lock_guard<std::mutex> lock(m);
|
|
auto it = cc_idx_to_pci_map.find(cc_idx);
|
|
return (it != cc_idx_to_pci_map.cend()) ? it->second : 999;
|
|
}
|
|
|
|
private:
|
|
srslog::log_channel& event_channel;
|
|
event_logger::asn1_output_format asn1_format;
|
|
std::unordered_map<uint32_t, uint32_t> cc_idx_to_pci_map;
|
|
mutable std::mutex m;
|
|
};
|
|
|
|
} // 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, asn1_output_format asn1_format)
|
|
{
|
|
pimpl = std::unique_ptr<logging_event_logger>(new logging_event_logger(c, asn1_format));
|
|
}
|