diff --git a/srsgnb/hdr/stack/ric/e2sm_kpm.h b/srsgnb/hdr/stack/ric/e2sm_kpm.h index 86084fa1d..ea8ba91ca 100644 --- a/srsgnb/hdr/stack/ric/e2sm_kpm.h +++ b/srsgnb/hdr/stack/ric/e2sm_kpm.h @@ -23,6 +23,8 @@ using namespace asn1::e2ap; using namespace asn1::e2sm_kpm; +class e2sm_kpm_report_service; + class e2sm_kpm : public e2sm { public: @@ -43,41 +45,17 @@ public: virtual void receive_e2_metrics_callback(const enb_metrics_t& m); -private: - bool _process_ric_action_definition_format1(e2_sm_kpm_action_definition_format1_s& action_definition_format1); - bool _process_ric_action_definition_format2(e2_sm_kpm_action_definition_format2_s& action_definition_format2); - bool _process_ric_action_definition_format3(e2_sm_kpm_action_definition_format3_s& action_definition_format3); - bool _process_ric_action_definition_format4(e2_sm_kpm_action_definition_format4_s& action_definition_format4); - bool _process_ric_action_definition_format5(e2_sm_kpm_action_definition_format5_s& action_definition_format5); - - bool _initialize_ric_ind_msg_style1(uint32_t action_id, - e2_sm_kpm_action_definition_format1_s& action, - e2_sm_kpm_ind_msg_format1_s& ric_ind_msg); - - bool _clear_action_data(E2SM_KPM_action_data_t& action_data); - - meas_record_item_c::types - _get_meas_data_type(std::string meas_name, e2sm_kpm_label_enum label, meas_record_l& meas_record_list); + bool _get_meas_definition(std::string meas_name, E2SM_KPM_metric_t& def); + bool _extract_last_integer_type_meas_value(E2SM_KPM_meas_value_t& meas_value, const enb_metrics_t& enb_metrics); + bool _extract_last_real_type_meas_value(E2SM_KPM_meas_value_t& meas_value, const enb_metrics_t& enb_metrics); + srslog::basic_logger& logger; - void _add_measurement_record(E2SM_KPM_meas_value_t& meas_value, meas_record_l& meas_record_list); +private: bool _generate_indication_header(e2_sm_kpm_ind_hdr_s& hdr, srsran::unique_byte_buffer_t& buf); bool _generate_indication_message(e2_sm_kpm_ind_msg_s& msg, srsran::unique_byte_buffer_t& buf); - bool _get_meas_definition(std::string meas_name, E2SM_KPM_metric_t& def); - meas_data_item_s& _get_meas_data_item_style1(e2_sm_kpm_ind_msg_s& ric_ind_msg, - std::string meas_name, - e2sm_kpm_label_enum label, - uint32_t ue_id, - bool& ref_found); - - std::vector _get_present_labels(const meas_info_item_s& action_meas_info_item); - - bool _extract_last_integer_type_meas_value(E2SM_KPM_meas_value_t& meas_value, const enb_metrics_t& enb_metrics); - bool _extract_last_real_type_meas_value(E2SM_KPM_meas_value_t& meas_value, const enb_metrics_t& enb_metrics); - - srslog::basic_logger& logger; - std::vector supported_meas_types; - std::map registered_actions_data; + std::vector supported_meas_types; + std::map registered_actions_data; srsran_random_t random_gen; diff --git a/srsgnb/hdr/stack/ric/e2sm_kpm_common.h b/srsgnb/hdr/stack/ric/e2sm_kpm_common.h index cb2b90499..9a2a873f6 100644 --- a/srsgnb/hdr/stack/ric/e2sm_kpm_common.h +++ b/srsgnb/hdr/stack/ric/e2sm_kpm_common.h @@ -22,14 +22,6 @@ using namespace asn1::e2ap; using namespace asn1::e2sm_kpm; -typedef struct { - uint16_t action_id; - e2_sm_kpm_action_definition_s action_definition; - e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types ind_msg_format; - e2_sm_kpm_ind_hdr_s ric_ind_header; - e2_sm_kpm_ind_msg_s ric_ind_message; -} E2SM_KPM_action_data_t; - enum e2_metric_data_type_t { INTEGER, REAL }; typedef struct { diff --git a/srsgnb/hdr/stack/ric/e2sm_kpm_report_service.h b/srsgnb/hdr/stack/ric/e2sm_kpm_report_service.h new file mode 100644 index 000000000..e746190ea --- /dev/null +++ b/srsgnb/hdr/stack/ric/e2sm_kpm_report_service.h @@ -0,0 +1,79 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2022 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 "srsgnb/hdr/stack/ric/e2sm_kpm.h" +#include "srsgnb/hdr/stack/ric/e2sm_kpm_common.h" +#include "srsran/asn1/e2ap.h" +#include "srsran/asn1/e2sm.h" +#include "srsran/asn1/e2sm_kpm_v2.h" +#include "srsran/srsran.h" + +#ifndef SRSRAN_E2SM_KPM_ACTION_DATA_H +#define SRSRAN_E2SM_KPM_ACTION_DATA_H + +using namespace asn1::e2ap; +using namespace asn1::e2sm_kpm; + +class e2sm_kpm_report_service +{ +public: + e2sm_kpm_report_service() = delete; + e2sm_kpm_report_service(e2sm_kpm* e2sm_kpm, uint16_t action_id, e2_sm_kpm_action_definition_s action_definition); + virtual ~e2sm_kpm_report_service() = default; + + virtual bool _initialize_ric_ind_hdr(); + virtual bool _initialize_ric_ind_msg() = 0; + virtual bool collect_data(const enb_metrics_t& enb_metrics) = 0; + virtual bool clear_collected_data() = 0; + + std::vector _get_present_labels(const meas_info_item_s& action_meas_info_item); + meas_record_item_c::types + _get_meas_data_type(std::string meas_name, e2sm_kpm_label_enum label, meas_record_l& meas_record_list); + void _add_measurement_record(E2SM_KPM_meas_value_t& meas_value, meas_record_l& meas_record_list); + + e2_sm_kpm_ind_hdr_s& get_ind_hdr() { return ric_ind_header_generic; }; + e2_sm_kpm_ind_msg_s& get_ind_msg() { return ric_ind_message_generic; }; + + e2sm_kpm* parent; + uint16_t action_id; + e2_sm_kpm_action_definition_s action_def_generic; + e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types ind_msg_format; + e2_sm_kpm_ind_hdr_s ric_ind_header_generic; + e2_sm_kpm_ind_msg_s ric_ind_message_generic; + + // hdr format 1 in base class, as all types use it + e2_sm_kpm_ind_hdr_format1_s& ric_ind_header; +}; + +class e2sm_kpm_report_service_style1 : public e2sm_kpm_report_service +{ +public: + e2sm_kpm_report_service_style1(e2sm_kpm* e2sm_kpm, + uint16_t action_id, + e2_sm_kpm_action_definition_s action_definition); + + static bool process_ric_action_definition(e2sm_kpm* e2sm_kpm, e2_sm_kpm_action_definition_s& action_definition); + + virtual bool _initialize_ric_ind_msg(); + virtual bool collect_data(const enb_metrics_t& enb_metrics); + virtual bool clear_collected_data(); + +private: + meas_data_item_s& + _get_meas_data_item(std::string meas_name, e2sm_kpm_label_enum label, uint32_t ue_id, bool& ref_found); + + e2_sm_kpm_action_definition_format1_s& action_def; + e2_sm_kpm_ind_msg_format1_s& ric_ind_message; +}; + +#endif // SRSRAN_E2SM_KPM_ACTION_DATA_H diff --git a/srsgnb/src/stack/ric/CMakeLists.txt b/srsgnb/src/stack/ric/CMakeLists.txt index 17d368003..0082f7333 100644 --- a/srsgnb/src/stack/ric/CMakeLists.txt +++ b/srsgnb/src/stack/ric/CMakeLists.txt @@ -1,4 +1,4 @@ -set(SOURCES ric_client.cc ric_subscription.cc e2ap.cc e2sm_kpm.cc) +set(SOURCES ric_client.cc ric_subscription.cc e2ap.cc e2sm_kpm.cc e2sm_kpm_report_service.cc) add_library(srsgnb_ric STATIC ${SOURCES}) target_link_libraries(srsgnb_ric srsran_asn1 ric_e2) diff --git a/srsgnb/src/stack/ric/e2sm_kpm.cc b/srsgnb/src/stack/ric/e2sm_kpm.cc index 42087bfca..9d2ad9ec0 100644 --- a/srsgnb/src/stack/ric/e2sm_kpm.cc +++ b/srsgnb/src/stack/ric/e2sm_kpm.cc @@ -13,6 +13,7 @@ #include "srsgnb/hdr/stack/ric/e2sm_kpm.h" #include "srsgnb/hdr/stack/ric/e2sm_kpm_metrics.h" +#include "srsgnb/hdr/stack/ric/e2sm_kpm_report_service.h" #include const std::string e2sm_kpm::short_name = "ORAN-E2SM-KPM"; @@ -47,105 +48,14 @@ e2sm_kpm::e2sm_kpm(srslog::basic_logger& logger_) : e2sm(short_name, oid, func_d } } -std::vector e2sm_kpm::_get_present_labels(const meas_info_item_s& action_meas_info_item) -{ - std::vector labels; - // TODO: add all labels defined in e2sm_kpm doc - for (uint32_t l = 0; l < action_meas_info_item.label_info_list.size(); l++) { - if (action_meas_info_item.label_info_list[l].meas_label.no_label_present) { - labels.push_back(NO_LABEL); - } - if (action_meas_info_item.label_info_list[l].meas_label.min_present) { - labels.push_back(MIN_LABEL); - } - if (action_meas_info_item.label_info_list[l].meas_label.max_present) { - labels.push_back(MAX_LABEL); - } - if (action_meas_info_item.label_info_list[l].meas_label.avg_present) { - labels.push_back(AVG_LABEL); - } - if (action_meas_info_item.label_info_list[l].meas_label.sum_present) { - labels.push_back(SUM_LABEL); - } - } - return labels; -} - void e2sm_kpm::receive_e2_metrics_callback(const enb_metrics_t& m) { last_enb_metrics = m; logger.debug("e2sm_kpm received new enb metrics, CPU0 Load: %.1f", last_enb_metrics.sys.cpu_load[0]); for (auto& it : registered_actions_data) { - uint32_t action_id = it.first; - e2_sm_kpm_action_definition_s& action = it.second.action_definition; - e2_sm_kpm_ind_msg_s& ric_ind_msg = it.second.ric_ind_message; - meas_info_list_l meas_info_list; - - switch (action.ric_style_type) { - case 1: - meas_info_list = ric_ind_msg.ind_msg_formats.ind_msg_format1().meas_info_list; - for (uint32_t i = 0; i < meas_info_list.size(); i++) { - meas_info_item_s meas_def_item = meas_info_list[i]; - std::string meas_name = meas_def_item.meas_type.meas_name().to_string(); - std::vector labels = _get_present_labels(meas_def_item); - - for (const auto& label : labels) { - // TODO: probably some labels need a special processing (e.g., use bin width that needs to be stored) - // get a proper record list - bool ref_found = false; - meas_data_item_s& meas_data_item = _get_meas_data_item_style1(ric_ind_msg, meas_name, label, 0, ref_found); - if (not ref_found) { - logger.info("Cannot find a meas record list, action_id %i, metric \"%s\" label: %i", - action_id, - meas_name.c_str(), - label); - return; - } - - // get data type - meas_record_item_c::types data_type = _get_meas_data_type(meas_name, label, meas_data_item.meas_record); - - // extract a needed value from enb metrics and add to the proper meas record list - E2SM_KPM_meas_value_t meas_value; - meas_value.name = meas_name; - meas_value.label = label; - // meas_values.scope = ...; - meas_value.data_type = data_type; - - if (meas_value.data_type == meas_record_item_c::types::options::integer) { - if (not _extract_last_integer_type_meas_value(meas_value, last_enb_metrics)) { - logger.info("Cannot extract value \"%s\" label: %i", meas_name.c_str(), label); - return; - } - } else { - // data_type == meas_record_item_c::types::options::real; - if (not _extract_last_real_type_meas_value(meas_value, last_enb_metrics)) { - logger.info("Cannot extract value \"%s\" label %i", meas_name.c_str(), label); - return; - } - } - // save meas value in the proper record list - _add_measurement_record(meas_value, meas_data_item.meas_record); - } - } - break; - case 2: - // TODO: add - break; - case 3: - // TODO: add - break; - case 4: - // TODO: add - break; - case 5: - // TODO: add - break; - default: - logger.info("Unknown RIC style type %i -> do not admit action %i (type %i)", action.ric_style_type); - return; - } + e2sm_kpm_report_service* report_service = it.second; + report_service->collect_data(m); } } @@ -172,7 +82,7 @@ bool e2sm_kpm::generate_ran_function_description(RANfunction_description& desc, event_trigger_style_list[0].ric_event_trigger_format_type = 1; // uses RIC Event Trigger Definition Format 1 // O-RAN.WG3.E2SM-KPM-R003-v03.00, 7.4.1 REPORT Service Style Type - /* + /* TODO: seems that flexric does not like this part and crashes auto& report_style_list = e2sm_kpm_ra_nfunction_description.ric_report_style_list; report_style_list.resize(5); @@ -246,9 +156,7 @@ bool e2sm_kpm::process_ric_event_trigger_definition(ricsubscription_request_s bool e2sm_kpm::process_ric_action_definition(ri_caction_to_be_setup_item_s ric_action, E2AP_RIC_action_t& action_entry) { - bool admit_action = false; - E2SM_KPM_action_data_t action_data; - + bool admit_action = false; e2_sm_kpm_action_definition_s e2sm_kpm_action_def; asn1::cbit_ref bref(ric_action.ric_action_definition.data(), ric_action.ric_action_definition.size()); @@ -258,24 +166,19 @@ bool e2sm_kpm::process_ric_action_definition(ri_caction_to_be_setup_item_s ric_a switch (e2sm_kpm_action_def.ric_style_type) { case 1: - admit_action = _process_ric_action_definition_format1( - e2sm_kpm_action_def.action_definition_formats.action_definition_format1()); + admit_action = e2sm_kpm_report_service_style1::process_ric_action_definition(this, e2sm_kpm_action_def); break; case 2: - admit_action = _process_ric_action_definition_format2( - e2sm_kpm_action_def.action_definition_formats.action_definition_format2()); + admit_action = false; break; case 3: - admit_action = _process_ric_action_definition_format3( - e2sm_kpm_action_def.action_definition_formats.action_definition_format3()); + admit_action = false; break; case 4: - admit_action = _process_ric_action_definition_format4( - e2sm_kpm_action_def.action_definition_formats.action_definition_format4()); + admit_action = false; break; case 5: - admit_action = _process_ric_action_definition_format5( - e2sm_kpm_action_def.action_definition_formats.action_definition_format5()); + admit_action = false; break; default: logger.info("Unknown RIC style type %i -> do not admit action %i (type %i)", @@ -290,45 +193,23 @@ bool e2sm_kpm::process_ric_action_definition(ri_caction_to_be_setup_item_s ric_a } action_entry.sm_local_ric_action_id = _generate_local_action_id(); - action_data.action_id = action_entry.sm_local_ric_action_id; - action_data.action_definition = e2sm_kpm_action_def; - - // initialize RIC indication header (always the same type 1) - action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().collet_start_time.from_number(std::time(0)); - // action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().file_formatversion.from_string(hdr.file_formatversion); - // action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().sender_name.from_string(hdr.sender_name); - // action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().sender_type.from_string(hdr.sender_type); - // action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().vendor_name.from_string(hdr.vendor_name); - - // initialize RIC indication message + e2sm_kpm_report_service* report_service; switch (e2sm_kpm_action_def.ric_style_type) { case 1: - action_data.ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format1; - action_data.ric_ind_message.ind_msg_formats.set_ind_msg_format1(); - _initialize_ric_ind_msg_style1( - action_entry.sm_local_ric_action_id, - action_data.action_definition.action_definition_formats.action_definition_format1(), - action_data.ric_ind_message.ind_msg_formats.ind_msg_format1()); + report_service = + new e2sm_kpm_report_service_style1(this, action_entry.sm_local_ric_action_id, e2sm_kpm_action_def); break; case 2: - action_data.ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format1; - action_data.ric_ind_message.ind_msg_formats.set_ind_msg_format1(); - // TODO: add initialization + admit_action = false; break; case 3: - action_data.ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format2; - action_data.ric_ind_message.ind_msg_formats.set_ind_msg_format2(); - // TODO: add initialization + admit_action = false; break; case 4: - action_data.ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format3; - action_data.ric_ind_message.ind_msg_formats.set_ind_msg_format3(); - // TODO: add initialization + admit_action = false; break; case 5: - action_data.ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format3; - action_data.ric_ind_message.ind_msg_formats.set_ind_msg_format3(); - // TODO: add initialization + admit_action = false; break; default: logger.info("Unknown RIC style type %i -> do not admit action %i (type %i)", @@ -339,96 +220,15 @@ bool e2sm_kpm::process_ric_action_definition(ri_caction_to_be_setup_item_s ric_a } registered_actions_data.insert( - std::pair(action_entry.sm_local_ric_action_id, action_data)); + std::pair(action_entry.sm_local_ric_action_id, report_service)); return admit_action; } -bool e2sm_kpm::_process_ric_action_definition_format1(e2_sm_kpm_action_definition_format1_s& action_definition_format1) -{ - uint64_t granul_period; - uint64_t eutra_cell_id; - uint64_t plmn_id; - ueid_c ue_id; - meas_info_list_l meas_info_list; - - granul_period = action_definition_format1.granul_period; - - if (granul_period == 0) { - logger.debug("Action granularity period of %i is not supported -> do not admitted action\n", granul_period); - return false; - } - - if (action_definition_format1.cell_global_id_present) { - if (action_definition_format1.cell_global_id.type() == cgi_c::types_opts::eutra_cgi) { - eutra_cell_id = action_definition_format1.cell_global_id.eutra_cgi().eutra_cell_id.to_number(); - plmn_id = action_definition_format1.cell_global_id.eutra_cgi().plmn_id.to_number(); - logger.debug("plmn_id 0x%x, eutra_cell_id %i", plmn_id, eutra_cell_id); - // TODO: check if E2 node has cell_id and plmn_id - } - } - - meas_info_list = action_definition_format1.meas_info_list; - for (uint32_t i = 0; i < meas_info_list.size(); i++) { - std::string meas_name = meas_info_list[i].meas_type.meas_name().to_string(); - E2SM_KPM_metric_t metric_definition; - if (not _get_meas_definition(meas_name, metric_definition)) { - printf("Unsupported measurement name: \"%s\" --> do not admit action\n", meas_name.c_str()); - return false; - } - - printf("Admitted action: measurement name: \"%s\" with the following labels: \n", meas_name.c_str()); - // TODO: add all labels defined in e2sm_kpm doc, if at least one label not supported do not admit action? - for (uint32_t l = 0; l < meas_info_list[i].label_info_list.size(); l++) { - if (meas_info_list[i].label_info_list[l].meas_label.no_label_present) { - if (metric_definition.supported_labels & NO_LABEL) { - printf("--- Label %i: NO LABEL\n", i); - } - } - if (meas_info_list[i].label_info_list[l].meas_label.min_present) { - if (metric_definition.supported_labels & MIN_LABEL) { - printf("--- Label %i: MIN\n", i); - } - } - if (meas_info_list[i].label_info_list[l].meas_label.max_present) { - if (metric_definition.supported_labels & MAX_LABEL) { - printf("--- Label %i: MAX\n", i); - } - } - if (meas_info_list[i].label_info_list[l].meas_label.avg_present) { - if (metric_definition.supported_labels & AVG_LABEL) { - printf("--- Label %i: AVG\n", i); - } - } - } - } - - return true; -} - -bool e2sm_kpm::_process_ric_action_definition_format2(e2_sm_kpm_action_definition_format2_s& action_definition_format2) -{ - return false; -} - -bool e2sm_kpm::_process_ric_action_definition_format3(e2_sm_kpm_action_definition_format3_s& action_definition_format3) -{ - return false; -} - -bool e2sm_kpm::_process_ric_action_definition_format4(e2_sm_kpm_action_definition_format4_s& action_definition_format4) -{ - return false; -} - -bool e2sm_kpm::_process_ric_action_definition_format5(e2_sm_kpm_action_definition_format5_s& action_definition_format5) -{ - return false; -} - bool e2sm_kpm::remove_ric_action_definition(E2AP_RIC_action_t& action_entry) { if (registered_actions_data.count(action_entry.sm_local_ric_action_id)) { + delete registered_actions_data.at(action_entry.sm_local_ric_action_id); registered_actions_data.erase(action_entry.sm_local_ric_action_id); return true; } @@ -445,86 +245,19 @@ bool e2sm_kpm::execute_action_fill_ric_indication(E2AP_RIC_action_t& action_entr action_entry.sm_local_ric_action_id); return false; } - E2SM_KPM_action_data_t& action_data = registered_actions_data.at(action_id); - ric_indication.indication_type = ri_cind_type_opts::report; + e2sm_kpm_report_service* report_service = registered_actions_data.at(action_id); + ric_indication.indication_type = ri_cind_type_opts::report; // header is the same for all RIC service styles, i.e., type 1 ric_indication.ri_cind_hdr = srsran::make_byte_buffer(); - this->_generate_indication_header(action_data.ric_ind_header, ric_indication.ri_cind_hdr); + this->_generate_indication_header(report_service->get_ind_hdr(), ric_indication.ri_cind_hdr); logger.info("Generating E2-SM-KPM Indication Message"); ric_indication.ri_cind_msg = srsran::make_byte_buffer(); - this->_generate_indication_message(action_data.ric_ind_message, ric_indication.ri_cind_msg); + this->_generate_indication_message(report_service->get_ind_msg(), ric_indication.ri_cind_msg); // clear data collected for this action - _clear_action_data(action_data); - return true; -} - -bool e2sm_kpm::_initialize_ric_ind_msg_style1(uint32_t action_id, - e2_sm_kpm_action_definition_format1_s& action, - e2_sm_kpm_ind_msg_format1_s& ric_ind_msg) -{ - meas_info_list_l action_meas_info_list = action.meas_info_list; - - // ric_ind_message.granul_period = action.granul_period; // not implemented by flexric and crashes it - ric_ind_msg.granul_period = 0; - ric_ind_msg.meas_info_list.resize(action_meas_info_list.size()); - ric_ind_msg.meas_data.resize(action_meas_info_list.size()); - - // add measurement info - for (uint32_t i = 0; i < ric_ind_msg.meas_info_list.size(); i++) { - // structs to fill - meas_info_item_s& meas_info_item = ric_ind_msg.meas_info_list[i]; - - // measurements definition - meas_info_item_s meas_def_item = action_meas_info_list[i]; - std::string meas_name = meas_def_item.meas_type.meas_name().to_string(); - - meas_info_item.meas_type.set_meas_name().from_string(meas_name.c_str()); - meas_info_item.label_info_list.resize(meas_def_item.label_info_list.size()); - - // TODO: add all labels defined in e2sm_kpm doc - for (uint32_t l = 0; l < meas_def_item.label_info_list.size(); l++) { - if (meas_def_item.label_info_list[l].meas_label.no_label_present) { - meas_info_item.label_info_list[l].meas_label.no_label_present = true; - meas_info_item.label_info_list[l].meas_label.no_label = meas_label_s::no_label_opts::true_value; - } - if (meas_def_item.label_info_list[l].meas_label.min_present) { - meas_info_item.label_info_list[l].meas_label.min_present = true; - meas_info_item.label_info_list[l].meas_label.min = meas_label_s::min_opts::true_value; - } - if (meas_def_item.label_info_list[l].meas_label.max_present) { - meas_info_item.label_info_list[l].meas_label.max_present = true; - meas_info_item.label_info_list[l].meas_label.max = meas_label_s::max_opts::true_value; - } - if (meas_def_item.label_info_list[l].meas_label.avg_present) { - meas_info_item.label_info_list[l].meas_label.avg_present = true; - meas_info_item.label_info_list[l].meas_label.avg = meas_label_s::avg_opts::true_value; - } - if (meas_def_item.label_info_list[l].meas_label.sum_present) { - meas_info_item.label_info_list[l].meas_label.sum_present = true; - meas_info_item.label_info_list[l].meas_label.sum = meas_label_s::sum_opts::true_value; - } - } - } - - return true; -} - -bool e2sm_kpm::_clear_action_data(E2SM_KPM_action_data_t& action_data) -{ - switch (action_data.action_definition.ric_style_type) { - case 1: - action_data.ric_ind_header.ind_hdr_formats.ind_hdr_format1().collet_start_time.from_number(std::time(0)); - for (uint32_t i = 0; i < action_data.ric_ind_message.ind_msg_formats.ind_msg_format1().meas_data.size(); ++i) { - action_data.ric_ind_message.ind_msg_formats.ind_msg_format1().meas_data[i].meas_record.clear(); - } - break; - default: - break; - } - + report_service->clear_collected_data(); return true; } @@ -540,97 +273,6 @@ bool e2sm_kpm::_get_meas_definition(std::string meas_name, E2SM_KPM_metric_t& de return true; } -meas_data_item_s& e2sm_kpm::_get_meas_data_item_style1(e2_sm_kpm_ind_msg_s& ric_ind_msg_generic, - std::string meas_name, - e2sm_kpm_label_enum label, - uint32_t ue_id, - bool& ref_found) -{ - e2_sm_kpm_ind_msg_format1_s& ric_ind_msg = ric_ind_msg_generic.ind_msg_formats.ind_msg_format1(); - meas_info_list_l& meas_info_list = ric_ind_msg.meas_info_list; - ref_found = false; - // find proper index of the metric - for (uint32_t i = 0; i < meas_info_list.size(); i++) { - // measurements definition - meas_info_item_s meas_def_item = meas_info_list[i]; - std::string meas_def_name = meas_def_item.meas_type.meas_name().to_string(); - - // TODO: check if UE_ID matches (for format2 and 3) - // check if the metric name matches - if (meas_def_name != meas_name.c_str()) { - continue; - } - - // check if the metric label matches - // TODO: add all labels defined in e2sm_kpm doc - for (uint32_t l = 0; l < meas_def_item.label_info_list.size(); l++) { - if (meas_def_item.label_info_list[l].meas_label.no_label_present and label == NO_LABEL) { - ref_found = true; - return ric_ind_msg.meas_data[i]; - } - if (meas_def_item.label_info_list[l].meas_label.min_present and label == MIN_LABEL) { - ref_found = true; - return ric_ind_msg.meas_data[i]; - } - if (meas_def_item.label_info_list[l].meas_label.max_present and label == MAX_LABEL) { - ref_found = true; - return ric_ind_msg.meas_data[i]; - } - if (meas_def_item.label_info_list[l].meas_label.avg_present and label == AVG_LABEL) { - ref_found = true; - return ric_ind_msg.meas_data[i]; - } - if (meas_def_item.label_info_list[l].meas_label.sum_present and label == SUM_LABEL) { - ref_found = true; - return ric_ind_msg.meas_data[i]; - } - } - } - // TODO assert if match == false, has to be present as was created during initialization - ref_found = false; - return ric_ind_msg.meas_data[0]; -} - -meas_record_item_c::types -e2sm_kpm::_get_meas_data_type(std::string meas_name, e2sm_kpm_label_enum label, meas_record_l& meas_record_list) -{ - meas_record_item_c::types data_type = meas_record_item_c::types::options::nulltype; - // if no data collected check the type using metric definition - if (meas_record_list.size() == 0) { - E2SM_KPM_metric_t metric_definition; - if (not _get_meas_definition(meas_name, metric_definition)) { - logger.debug("No definition for measurement type \"%s\"", metric_definition.name); - return data_type; - } - if (metric_definition.data_type == INTEGER) { - data_type = meas_record_item_c::types::options::integer; - } else { - data_type = meas_record_item_c::types::options::real; - } - } else { - // check the data type of the first element in the list - data_type = meas_record_list[0].type(); - } - return data_type; -} - -void e2sm_kpm::_add_measurement_record(E2SM_KPM_meas_value_t& meas_value, meas_record_l& meas_record_list) -{ - if (meas_value.data_type == meas_record_item_c::types::options::integer) { - meas_record_item_c item; - item.set_integer() = meas_value.integer_value; - meas_record_list.push_back(item); - } else { - // data_type == meas_record_item_c::types::options::real; - meas_record_item_c item; - real_s real_value; - // TODO: real value seems to be not supported in asn1??? - // real_value.value = meas_value.real_value; - item.set_real() = real_value; - meas_record_list.push_back(item); - } -} - bool e2sm_kpm::_generate_indication_header(e2_sm_kpm_ind_hdr_s& hdr, srsran::unique_byte_buffer_t& buf) { asn1::bit_ref bref(buf->msg, buf->get_tailroom()); diff --git a/srsgnb/src/stack/ric/e2sm_kpm_report_service.cc b/srsgnb/src/stack/ric/e2sm_kpm_report_service.cc new file mode 100644 index 000000000..fc31945ee --- /dev/null +++ b/srsgnb/src/stack/ric/e2sm_kpm_report_service.cc @@ -0,0 +1,338 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2022 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 "srsgnb/hdr/stack/ric/e2sm_kpm_report_service.h" + +e2sm_kpm_report_service::e2sm_kpm_report_service(e2sm_kpm* e2sm_kpm, + uint16_t action_id, + e2_sm_kpm_action_definition_s action_definition) : + parent(e2sm_kpm), + action_id(action_id), + action_def_generic(action_definition), + ric_ind_header_generic(), + ric_ind_header(ric_ind_header_generic.ind_hdr_formats.ind_hdr_format1()) +{ +} + +std::vector +e2sm_kpm_report_service::_get_present_labels(const meas_info_item_s& action_meas_info_item) +{ + std::vector labels; + // TODO: add all labels defined in e2sm_kpm doc + for (uint32_t l = 0; l < action_meas_info_item.label_info_list.size(); l++) { + if (action_meas_info_item.label_info_list[l].meas_label.no_label_present) { + labels.push_back(NO_LABEL); + } + if (action_meas_info_item.label_info_list[l].meas_label.min_present) { + labels.push_back(MIN_LABEL); + } + if (action_meas_info_item.label_info_list[l].meas_label.max_present) { + labels.push_back(MAX_LABEL); + } + if (action_meas_info_item.label_info_list[l].meas_label.avg_present) { + labels.push_back(AVG_LABEL); + } + if (action_meas_info_item.label_info_list[l].meas_label.sum_present) { + labels.push_back(SUM_LABEL); + } + } + return labels; +} + +bool e2sm_kpm_report_service::_initialize_ric_ind_hdr() +{ + // TODO: set the remaining fields properly (they are optional) + ric_ind_header.collet_start_time.from_number(std::time(0)); + // ric_ind_header.file_formatversion.from_string(hdr.file_formatversion); + // ric_ind_header.sender_name.from_string(hdr.sender_name); + // ric_ind_header.sender_type.from_string(hdr.sender_type); + // ric_ind_header.vendor_name.from_string(hdr.vendor_name); + return true; +} + +meas_record_item_c::types e2sm_kpm_report_service::_get_meas_data_type(std::string meas_name, + e2sm_kpm_label_enum label, + meas_record_l& meas_record_list) +{ + meas_record_item_c::types data_type = meas_record_item_c::types::options::nulltype; + // if no data collected check the type using metric definition + if (meas_record_list.size() == 0) { + E2SM_KPM_metric_t metric_definition; + if (not parent->_get_meas_definition(meas_name, metric_definition)) { + parent->logger.debug("No definition for measurement type \"%s\"", metric_definition.name); + return data_type; + } + if (metric_definition.data_type == INTEGER) { + data_type = meas_record_item_c::types::options::integer; + } else { + data_type = meas_record_item_c::types::options::real; + } + } else { + // check the data type of the first element in the list + data_type = meas_record_list[0].type(); + } + return data_type; +} + +void e2sm_kpm_report_service::_add_measurement_record(E2SM_KPM_meas_value_t& meas_value, + meas_record_l& meas_record_list) +{ + if (meas_value.data_type == meas_record_item_c::types::options::integer) { + meas_record_item_c item; + item.set_integer() = meas_value.integer_value; + meas_record_list.push_back(item); + } else { + // data_type == meas_record_item_c::types::options::real; + meas_record_item_c item; + real_s real_value; + // TODO: real value seems to be not supported in asn1??? + // real_value.value = meas_value.real_value; + item.set_real() = real_value; + meas_record_list.push_back(item); + } +} + +e2sm_kpm_report_service_style1::e2sm_kpm_report_service_style1(e2sm_kpm* e2sm_kpm, + uint16_t action_id, + e2_sm_kpm_action_definition_s action_definition) : + e2sm_kpm_report_service(e2sm_kpm, action_id, action_definition), + action_def(action_def_generic.action_definition_formats.action_definition_format1()), + ric_ind_message(ric_ind_message_generic.ind_msg_formats.set_ind_msg_format1()) +{ + ind_msg_format = e2_sm_kpm_ind_msg_s::ind_msg_formats_c_::types_opts::ind_msg_format1; + this->_initialize_ric_ind_hdr(); + this->_initialize_ric_ind_msg(); +} + +bool e2sm_kpm_report_service_style1::_initialize_ric_ind_msg() +{ + meas_info_list_l action_meas_info_list = action_def.meas_info_list; + + // ric_ind_message.granul_period = action.granul_period; // not implemented by flexric and crashes it + ric_ind_message.granul_period = 0; + ric_ind_message.meas_info_list.resize(action_meas_info_list.size()); + ric_ind_message.meas_data.resize(action_meas_info_list.size()); + + // add measurement info + for (uint32_t i = 0; i < ric_ind_message.meas_info_list.size(); i++) { + // structs to fill + meas_info_item_s& meas_info_item = ric_ind_message.meas_info_list[i]; + + // measurements definition + meas_info_item_s& meas_def_item = action_meas_info_list[i]; + std::string meas_name = meas_def_item.meas_type.meas_name().to_string(); + + meas_info_item.meas_type.set_meas_name().from_string(meas_name.c_str()); + meas_info_item.label_info_list.resize(meas_def_item.label_info_list.size()); + + // TODO: add all labels defined in e2sm_kpm doc, make this part generic and put to the base class + for (uint32_t l = 0; l < meas_def_item.label_info_list.size(); l++) { + if (meas_def_item.label_info_list[l].meas_label.no_label_present) { + meas_info_item.label_info_list[l].meas_label.no_label_present = true; + meas_info_item.label_info_list[l].meas_label.no_label = meas_label_s::no_label_opts::true_value; + } + if (meas_def_item.label_info_list[l].meas_label.min_present) { + meas_info_item.label_info_list[l].meas_label.min_present = true; + meas_info_item.label_info_list[l].meas_label.min = meas_label_s::min_opts::true_value; + } + if (meas_def_item.label_info_list[l].meas_label.max_present) { + meas_info_item.label_info_list[l].meas_label.max_present = true; + meas_info_item.label_info_list[l].meas_label.max = meas_label_s::max_opts::true_value; + } + if (meas_def_item.label_info_list[l].meas_label.avg_present) { + meas_info_item.label_info_list[l].meas_label.avg_present = true; + meas_info_item.label_info_list[l].meas_label.avg = meas_label_s::avg_opts::true_value; + } + if (meas_def_item.label_info_list[l].meas_label.sum_present) { + meas_info_item.label_info_list[l].meas_label.sum_present = true; + meas_info_item.label_info_list[l].meas_label.sum = meas_label_s::sum_opts::true_value; + } + } + } + + return true; +} + +bool e2sm_kpm_report_service_style1::process_ric_action_definition(e2sm_kpm* e2sm_kpm, + e2_sm_kpm_action_definition_s& action_def_generic) +{ + e2_sm_kpm_action_definition_format1_s& action_definition = + action_def_generic.action_definition_formats.action_definition_format1(); + + uint64_t granul_period; + uint64_t eutra_cell_id; + uint64_t plmn_id; + ueid_c ue_id; + meas_info_list_l meas_info_list; + + granul_period = action_definition.granul_period; + + if (granul_period == 0) { + e2sm_kpm->logger.debug("Action granularity period of %i is not supported -> do not admitted action\n", + granul_period); + return false; + } + + if (action_definition.cell_global_id_present) { + if (action_definition.cell_global_id.type() == cgi_c::types_opts::eutra_cgi) { + eutra_cell_id = action_definition.cell_global_id.eutra_cgi().eutra_cell_id.to_number(); + plmn_id = action_definition.cell_global_id.eutra_cgi().plmn_id.to_number(); + e2sm_kpm->logger.debug("plmn_id 0x%x, eutra_cell_id %i", plmn_id, eutra_cell_id); + // TODO: check if E2 node has cell_id and plmn_id + } + } + + meas_info_list = action_definition.meas_info_list; + for (uint32_t i = 0; i < meas_info_list.size(); i++) { + std::string meas_name = meas_info_list[i].meas_type.meas_name().to_string(); + E2SM_KPM_metric_t metric_definition; + if (not e2sm_kpm->_get_meas_definition(meas_name, metric_definition)) { + printf("Unsupported measurement name: \"%s\" --> do not admit action\n", meas_name.c_str()); + return false; + } + + printf("Admitted action: measurement name: \"%s\" with the following labels: \n", meas_name.c_str()); + // TODO: add all labels defined in e2sm_kpm doc, if at least one label not supported do not admit action? + for (uint32_t l = 0; l < meas_info_list[i].label_info_list.size(); l++) { + if (meas_info_list[i].label_info_list[l].meas_label.no_label_present) { + if (metric_definition.supported_labels & NO_LABEL) { + printf("--- Label %i: NO LABEL\n", i); + } + } + if (meas_info_list[i].label_info_list[l].meas_label.min_present) { + if (metric_definition.supported_labels & MIN_LABEL) { + printf("--- Label %i: MIN\n", i); + } + } + if (meas_info_list[i].label_info_list[l].meas_label.max_present) { + if (metric_definition.supported_labels & MAX_LABEL) { + printf("--- Label %i: MAX\n", i); + } + } + if (meas_info_list[i].label_info_list[l].meas_label.avg_present) { + if (metric_definition.supported_labels & AVG_LABEL) { + printf("--- Label %i: AVG\n", i); + } + } + } + } + + return true; +} + +meas_data_item_s& e2sm_kpm_report_service_style1::_get_meas_data_item(std::string meas_name, + e2sm_kpm_label_enum label, + uint32_t ue_id, + bool& ref_found) +{ + meas_info_list_l& meas_info_list = ric_ind_message.meas_info_list; + ref_found = false; + // find proper index of the metric + for (uint32_t i = 0; i < meas_info_list.size(); i++) { + // measurements definition + meas_info_item_s meas_def_item = meas_info_list[i]; + std::string meas_def_name = meas_def_item.meas_type.meas_name().to_string(); + + // check if the metric name matches + if (meas_def_name != meas_name.c_str()) { + continue; + } + + // check if the metric label matches + // TODO: add all labels defined in e2sm_kpm doc + for (uint32_t l = 0; l < meas_def_item.label_info_list.size(); l++) { + if (meas_def_item.label_info_list[l].meas_label.no_label_present and label == NO_LABEL) { + ref_found = true; + return ric_ind_message.meas_data[i]; + } + if (meas_def_item.label_info_list[l].meas_label.min_present and label == MIN_LABEL) { + ref_found = true; + return ric_ind_message.meas_data[i]; + } + if (meas_def_item.label_info_list[l].meas_label.max_present and label == MAX_LABEL) { + ref_found = true; + return ric_ind_message.meas_data[i]; + } + if (meas_def_item.label_info_list[l].meas_label.avg_present and label == AVG_LABEL) { + ref_found = true; + return ric_ind_message.meas_data[i]; + } + if (meas_def_item.label_info_list[l].meas_label.sum_present and label == SUM_LABEL) { + ref_found = true; + return ric_ind_message.meas_data[i]; + } + } + } + // TODO assert if match == false, has to be present as was created during initialization + ref_found = false; + return ric_ind_message.meas_data[0]; +} + +bool e2sm_kpm_report_service_style1::collect_data(const enb_metrics_t& enb_metrics) +{ + meas_info_list_l& meas_info_list = ric_ind_message.meas_info_list; + for (uint32_t i = 0; i < meas_info_list.size(); i++) { + meas_info_item_s& meas_def_item = meas_info_list[i]; + std::string meas_name = meas_def_item.meas_type.meas_name().to_string(); + std::vector labels = _get_present_labels(meas_def_item); + + for (const auto& label : labels) { + // TODO: probably some labels need a special processing (e.g., use bin width that needs to be stored) + // get a proper record list + bool ref_found = false; + meas_data_item_s& meas_data_item = _get_meas_data_item(meas_name, label, 0, ref_found); + if (not ref_found) { + parent->logger.info("Cannot find a meas record list, action_id %i, metric \"%s\" label: %i", + action_id, + meas_name.c_str(), + label); + return false; + } + + // get data type + meas_record_item_c::types data_type = _get_meas_data_type(meas_name, label, meas_data_item.meas_record); + + // extract a needed value from enb metrics and add to the proper meas record list + E2SM_KPM_meas_value_t meas_value; + meas_value.name = meas_name; + meas_value.label = label; + // meas_values.scope = ...; + meas_value.data_type = data_type; + + if (meas_value.data_type == meas_record_item_c::types::options::integer) { + if (not parent->_extract_last_integer_type_meas_value(meas_value, enb_metrics)) { + parent->logger.info("Cannot extract value \"%s\" label: %i", meas_name.c_str(), label); + return false; + } + } else { + // data_type == meas_record_item_c::types::options::real; + if (not parent->_extract_last_real_type_meas_value(meas_value, enb_metrics)) { + parent->logger.info("Cannot extract value \"%s\" label %i", meas_name.c_str(), label); + return false; + } + } + // save meas value in the proper record list + _add_measurement_record(meas_value, meas_data_item.meas_record); + } + } + return true; +} + +bool e2sm_kpm_report_service_style1::clear_collected_data() +{ + ric_ind_header.collet_start_time.from_number(std::time(0)); + for (uint32_t i = 0; i < ric_ind_message.meas_data.size(); ++i) { + ric_ind_message.meas_data[i].meas_record.clear(); + } + return true; +} \ No newline at end of file