@@ -139,6 +139,41 @@ rlc_metrics generate_rlc_metrics(uint32_t ue_idx, uint32_t bearer_id)
139139 return rlc_metric;
140140}
141141
142+ scheduler_cell_metrics generate_sched_metrics (uint32_t nof_prbs,
143+ uint32_t nof_slots,
144+ std::vector<std::vector<uint32_t >> dl_grants,
145+ std::vector<std::vector<uint32_t >> ul_grants)
146+ {
147+ scheduler_cell_metrics sched_metric;
148+ sched_metric.nof_prbs = nof_prbs;
149+ sched_metric.nof_dl_slots = nof_slots;
150+ sched_metric.nof_ul_slots = nof_slots;
151+
152+ assert (dl_grants[0 ].size () == nof_slots);
153+ assert (ul_grants[0 ].size () == nof_slots);
154+
155+ for (uint32_t ue_idx = 0 ; ue_idx < nof_slots; ++ue_idx) {
156+ scheduler_ue_metrics ue_metrics = {0 };
157+ ue_metrics.pci = 1 ;
158+ ue_metrics.rnti = static_cast <rnti_t >(0x1000 + ue_idx);
159+ ue_metrics.tot_dl_prbs_used =
160+ (ue_idx < dl_grants.size ()) ? std::accumulate (dl_grants[ue_idx].begin (), dl_grants[ue_idx].end (), 0 ) : 0 ;
161+ ue_metrics.mean_dl_prbs_used =
162+ sched_metric.nof_dl_slots > 0
163+ ? static_cast <double >(1.0 * ue_metrics.tot_dl_prbs_used / sched_metric.nof_dl_slots )
164+ : 0 ;
165+ ue_metrics.tot_ul_prbs_used =
166+ (ue_idx < ul_grants.size ()) ? std::accumulate (ul_grants[ue_idx].begin (), ul_grants[ue_idx].end (), 0 ) : 0 ;
167+ ue_metrics.mean_ul_prbs_used =
168+ sched_metric.nof_ul_slots > 0
169+ ? static_cast <double >(1.0 * ue_metrics.tot_ul_prbs_used / sched_metric.nof_ul_slots )
170+ : 0 ;
171+ sched_metric.ue_metrics .push_back (ue_metrics);
172+ }
173+
174+ return sched_metric;
175+ }
176+
142177#if PCAP_OUTPUT
143178TEST_F (e2_entity_test, e2sm_kpm_generates_ran_func_desc)
144179{
@@ -384,3 +419,110 @@ TEST_F(e2sm_kpm_meas_provider_test, e2sm_kpm_ind_e2_level_rlc_metrics)
384419 save_msg_pcap (gw->last_pdu );
385420#endif
386421}
422+
423+ TEST_F (e2sm_kpm_meas_provider_test, e2sm_kpm_ind_e2_level_prb_metrics)
424+ {
425+ std::vector<uint32_t > grants_ue0 = {1 , 0 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 };
426+ std::vector<uint32_t > grants_ue1 = {0 , 0 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 };
427+ std::vector<uint32_t > grants_ue2 = {5 , 0 , 5 , 0 , 5 , 0 , 5 , 0 , 5 , 0 };
428+ std::vector<uint32_t > grants_ue3 = {0 , 0 , 0 , 0 , 0 , 5 , 5 , 5 , 5 , 5 };
429+ std::vector<std::vector<uint32_t >> dl_grants = {grants_ue0, grants_ue1, grants_ue2, grants_ue3};
430+ std::vector<std::vector<uint32_t >> ul_grants = {grants_ue0, grants_ue1};
431+
432+ uint32_t nof_prbs = 25 ;
433+ uint32_t nof_slots = grants_ue0.size ();
434+ uint32_t nof_meas_data = 1 ;
435+ uint32_t nof_records = 6 ;
436+
437+ uint32_t tot_dl_prbs = 0 ;
438+ uint32_t tot_ul_prbs = 0 ;
439+ for (const auto & grants : dl_grants) {
440+ tot_dl_prbs += std::accumulate (grants.begin (), grants.end (), 0 );
441+ }
442+ for (const auto & grants : ul_grants) {
443+ tot_ul_prbs += std::accumulate (grants.begin (), grants.end (), 0 );
444+ }
445+
446+ uint32_t expected_dl_used_prbs = tot_dl_prbs / nof_slots;
447+ uint32_t expected_ul_used_prbs = tot_ul_prbs / nof_slots;
448+ uint32_t expected_dl_avail_prbs = nof_prbs - expected_dl_used_prbs;
449+ uint32_t expected_ul_avail_prbs = nof_prbs - expected_ul_used_prbs;
450+ uint32_t expected_dl_tot_prbs = 100.0 * expected_dl_used_prbs / nof_prbs;
451+ uint32_t expected_ul_tot_prbs = 100.0 * expected_ul_used_prbs / nof_prbs;
452+
453+ // Define E2SM_KPM action format 1.
454+ asn1::e2sm::e2sm_kpm_action_definition_s action_def;
455+ action_def.ric_style_type = 1 ;
456+ asn1::e2sm::e2sm_kpm_action_definition_format1_s& action_def_f1 =
457+ action_def.action_definition_formats .set_action_definition_format1 ();
458+ action_def_f1.cell_global_id_present = false ;
459+ action_def_f1.granul_period = 100 ;
460+
461+ asn1::e2sm::meas_info_item_s meas_info_item{};
462+ asn1::e2sm::label_info_item_s label_info_item{};
463+ label_info_item.meas_label .no_label_present = true ;
464+ label_info_item.meas_label .no_label = asn1::e2sm::meas_label_s::no_label_opts::true_value;
465+ meas_info_item.label_info_list .push_back (label_info_item);
466+
467+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbUsedDl" );
468+ action_def_f1.meas_info_list .push_back (meas_info_item);
469+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbUsedUl" );
470+ action_def_f1.meas_info_list .push_back (meas_info_item);
471+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbAvailDl" );
472+ action_def_f1.meas_info_list .push_back (meas_info_item);
473+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbAvailUl" );
474+ action_def_f1.meas_info_list .push_back (meas_info_item);
475+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbTotDl" );
476+ action_def_f1.meas_info_list .push_back (meas_info_item);
477+ meas_info_item.meas_type .set_meas_name ().from_string (" RRU.PrbTotUl" );
478+ action_def_f1.meas_info_list .push_back (meas_info_item);
479+
480+ asn1::e2ap::ric_action_to_be_setup_item_s ric_action = generate_e2sm_kpm_ric_action (action_def);
481+
482+ #if PCAP_OUTPUT
483+ // Save E2 Subscription Request.
484+ e2_message e2_subscript_req = generate_e2sm_kpm_subscription_request (ric_action);
485+ packer->handle_message (e2_subscript_req);
486+ save_msg_pcap (gw->last_pdu );
487+ #endif
488+
489+ ASSERT_TRUE (e2sm_iface->action_supported (ric_action));
490+ auto report_service = e2sm_iface->get_e2sm_report_service (ric_action.ric_action_definition );
491+
492+ // Push dummy metric measurements.
493+ scheduler_cell_metrics sched_metrics;
494+ sched_metrics = generate_sched_metrics (nof_prbs, nof_slots, dl_grants, ul_grants);
495+ du_metrics->report_metrics (sched_metrics);
496+
497+ // Trigger measurement collection.
498+ report_service->collect_measurements ();
499+
500+ TESTASSERT_EQ (true , report_service->is_ind_msg_ready ());
501+ // Get RIC indication msg content.
502+ byte_buffer ind_hdr_bytes = report_service->get_indication_header ();
503+ byte_buffer ind_msg_bytes = report_service->get_indication_message ();
504+
505+ // Decode RIC Indication and check the content.
506+ asn1::e2sm::e2sm_kpm_ind_msg_s ric_ind_msg;
507+ asn1::cbit_ref ric_ind_bref (ind_msg_bytes);
508+ if (ric_ind_msg.unpack (ric_ind_bref) != asn1::SRSASN_SUCCESS) {
509+ test_logger.debug (" e2sm_kpm: RIC indication msg could not be unpacked" );
510+ return ;
511+ }
512+
513+ TESTASSERT_EQ (nof_meas_data, ric_ind_msg.ind_msg_formats .ind_msg_format1 ().meas_data .size ());
514+ auto & meas_record = ric_ind_msg.ind_msg_formats .ind_msg_format1 ().meas_data [0 ].meas_record ;
515+ TESTASSERT_EQ (nof_records, meas_record.size ());
516+ TESTASSERT_EQ (expected_dl_used_prbs, meas_record[0 ].integer ());
517+ TESTASSERT_EQ (expected_ul_used_prbs, meas_record[1 ].integer ());
518+ TESTASSERT_EQ (expected_dl_avail_prbs, meas_record[2 ].integer ());
519+ TESTASSERT_EQ (expected_ul_avail_prbs, meas_record[3 ].integer ());
520+ TESTASSERT_EQ (expected_dl_tot_prbs, meas_record[4 ].integer ());
521+ TESTASSERT_EQ (expected_ul_tot_prbs, meas_record[5 ].integer ());
522+
523+ #if PCAP_OUTPUT
524+ e2_message e2_msg = generate_e2_ind_msg (ind_hdr_bytes, ind_msg_bytes);
525+ packer->handle_message (e2_msg);
526+ save_msg_pcap (gw->last_pdu );
527+ #endif
528+ }
0 commit comments