Skip to content

Commit 34b6173

Browse files
Piotr Gawlowiczcodebot
authored andcommitted
e2sm_kpm: add RRU.PrbUsedDl and RRU.PrbUsedUl, add test
1 parent 349e976 commit 34b6173

File tree

3 files changed

+234
-0
lines changed

3 files changed

+234
-0
lines changed

lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ e2sm_kpm_du_meas_provider_impl::e2sm_kpm_du_meas_provider_impl(srs_du::f1ap_ue_i
3535
e2sm_kpm_supported_metric_t{
3636
NO_LABEL, E2_NODE_LEVEL | UE_LEVEL, true, &e2sm_kpm_du_meas_provider_impl::get_prb_avail_ul});
3737

38+
supported_metrics.emplace(
39+
"RRU.PrbUsedDl",
40+
e2sm_kpm_supported_metric_t{
41+
NO_LABEL, E2_NODE_LEVEL | UE_LEVEL, true, &e2sm_kpm_du_meas_provider_impl::get_prb_used_dl});
42+
43+
supported_metrics.emplace(
44+
"RRU.PrbUsedUl",
45+
e2sm_kpm_supported_metric_t{
46+
NO_LABEL, E2_NODE_LEVEL | UE_LEVEL, true, &e2sm_kpm_du_meas_provider_impl::get_prb_used_ul});
47+
3848
supported_metrics.emplace(
3949
"RRU.PrbTotDl",
4050
e2sm_kpm_supported_metric_t{
@@ -408,6 +418,86 @@ bool e2sm_kpm_du_meas_provider_impl::get_prb_avail_ul(const asn1::e2sm::label_in
408418
return meas_collected;
409419
}
410420

421+
bool e2sm_kpm_du_meas_provider_impl::get_prb_used_dl(const asn1::e2sm::label_info_list_l label_info_list,
422+
const std::vector<asn1::e2sm::ue_id_c>& ues,
423+
const std::optional<asn1::e2sm::cgi_c> cell_global_id,
424+
std::vector<asn1::e2sm::meas_record_item_c>& items)
425+
{
426+
bool meas_collected = false;
427+
if (last_ue_metrics.empty()) {
428+
return handle_no_meas_data_available(ues, items, asn1::e2sm::meas_record_item_c::types::options::integer);
429+
}
430+
if ((label_info_list.size() > 1 or
431+
(label_info_list.size() == 1 and not label_info_list[0].meas_label.no_label_present))) {
432+
logger.debug("Metric: RRU.PrbUsedDl supports only NO_LABEL label.");
433+
return meas_collected;
434+
}
435+
436+
if (ues.empty()) {
437+
double dl_prbs_used =
438+
std::accumulate(last_ue_metrics.begin(),
439+
last_ue_metrics.end(),
440+
0,
441+
[](size_t sum, const scheduler_ue_metrics& metric) { return sum + metric.tot_dl_prbs_used; }) /
442+
nof_dl_slots;
443+
meas_record_item_c meas_record_item;
444+
meas_record_item.set_integer() = dl_prbs_used;
445+
items.push_back(meas_record_item);
446+
meas_collected = true;
447+
}
448+
449+
for (auto& ue : ues) {
450+
gnb_cu_ue_f1ap_id_t gnb_cu_ue_f1ap_id = int_to_gnb_cu_ue_f1ap_id(ue.gnb_du_ue_id().gnb_cu_ue_f1ap_id);
451+
uint32_t ue_idx = f1ap_ue_id_provider.get_ue_index(gnb_cu_ue_f1ap_id);
452+
meas_record_item_c meas_record_item;
453+
meas_record_item.set_integer() = last_ue_metrics[ue_idx].mean_dl_prbs_used;
454+
items.push_back(meas_record_item);
455+
meas_collected = true;
456+
}
457+
458+
return meas_collected;
459+
}
460+
461+
bool e2sm_kpm_du_meas_provider_impl::get_prb_used_ul(const asn1::e2sm::label_info_list_l label_info_list,
462+
const std::vector<asn1::e2sm::ue_id_c>& ues,
463+
const std::optional<asn1::e2sm::cgi_c> cell_global_id,
464+
std::vector<asn1::e2sm::meas_record_item_c>& items)
465+
{
466+
bool meas_collected = false;
467+
if (last_ue_metrics.empty()) {
468+
return handle_no_meas_data_available(ues, items, asn1::e2sm::meas_record_item_c::types::options::integer);
469+
}
470+
if ((label_info_list.size() > 1 or
471+
(label_info_list.size() == 1 and not label_info_list[0].meas_label.no_label_present))) {
472+
logger.debug("Metric: RRU.PrbUsedUl supports only NO_LABEL label.");
473+
return meas_collected;
474+
}
475+
476+
if (ues.empty()) {
477+
double ul_prbs_used =
478+
std::accumulate(last_ue_metrics.begin(),
479+
last_ue_metrics.end(),
480+
0,
481+
[](size_t sum, const scheduler_ue_metrics& metric) { return sum + metric.tot_ul_prbs_used; }) /
482+
nof_ul_slots;
483+
meas_record_item_c meas_record_item;
484+
meas_record_item.set_integer() = ul_prbs_used;
485+
items.push_back(meas_record_item);
486+
meas_collected = true;
487+
}
488+
489+
for (auto& ue : ues) {
490+
gnb_cu_ue_f1ap_id_t gnb_cu_ue_f1ap_id = int_to_gnb_cu_ue_f1ap_id(ue.gnb_du_ue_id().gnb_cu_ue_f1ap_id);
491+
uint32_t ue_idx = f1ap_ue_id_provider.get_ue_index(gnb_cu_ue_f1ap_id);
492+
meas_record_item_c meas_record_item;
493+
meas_record_item.set_integer() = last_ue_metrics[ue_idx].mean_ul_prbs_used;
494+
items.push_back(meas_record_item);
495+
meas_collected = true;
496+
}
497+
498+
return meas_collected;
499+
}
500+
411501
bool e2sm_kpm_du_meas_provider_impl::get_prb_use_perc_dl(const asn1::e2sm::label_info_list_l label_info_list,
412502
const std::vector<asn1::e2sm::ue_id_c>& ues,
413503
const std::optional<asn1::e2sm::cgi_c> cell_global_id,

lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class e2sm_kpm_du_meas_provider_impl : public e2sm_kpm_meas_provider, public e2_
9393
metric_meas_getter_func_t get_rsrq;
9494
metric_meas_getter_func_t get_prb_avail_dl;
9595
metric_meas_getter_func_t get_prb_avail_ul;
96+
metric_meas_getter_func_t get_prb_used_dl;
97+
metric_meas_getter_func_t get_prb_used_ul;
9698
metric_meas_getter_func_t get_prb_use_perc_dl;
9799
metric_meas_getter_func_t get_prb_use_perc_ul;
98100
metric_meas_getter_func_t get_delay_ul;

tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
143178
TEST_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

Comments
 (0)