Skip to content

Commit b672e27

Browse files
author
Pavel Harbanau
committed
ofh: enhance RU emulator statistics
1 parent 4ad3729 commit b672e27

File tree

8 files changed

+884
-123
lines changed

8 files changed

+884
-123
lines changed

tests/integrationtests/ofh/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ target_link_libraries(ofh_integration_test
1818
add_test(ofh_integration_test ofh_integration_test)
1919
set_tests_properties(ofh_integration_test PROPERTIES LABELS "tsan;NO_MEMCHECK")
2020

21-
set (SOURCES ru_emulator_cli11_schema.cpp ru_emulator.cpp ru_emulator_socket_transceiver.cpp)
21+
set (SOURCES
22+
ru_emulator_cli11_schema.cpp
23+
ru_emulator.cpp
24+
ru_emulator_rx_window_checker.cpp
25+
ru_emulator_socket_transceiver.cpp
26+
ru_emulator_timing_notifier.cpp)
2227
if (DPDK_FOUND)
2328
list(APPEND SOURCES ru_emulator_dpdk_transceiver.cpp)
2429
endif (DPDK_FOUND)

tests/integrationtests/ofh/ru_emulator.cpp

Lines changed: 368 additions & 118 deletions
Large diffs are not rendered by default.

tests/integrationtests/ofh/ru_emulator_appconfig.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,26 @@
1212

1313
#include "srsran/adt/optional.h"
1414
#include "srsran/ran/bs_channel_bandwidth.h"
15+
#include <srsran/srslog/srslog.h>
1516
#include <string>
1617
#include <vector>
1718

1819
namespace srsran {
1920

2021
/// RU emulator OFH configuration parameters.
2122
struct ru_emulator_ofh_appconfig {
23+
/// T2a maximum parameter for downlink Control-Plane in microseconds.
24+
std::chrono::microseconds T2a_max_cp_dl{500};
25+
/// T2a minimum parameter for downlink Control-Plane in microseconds.
26+
std::chrono::microseconds T2a_min_cp_dl{258};
27+
/// T2a maximum parameter for uplink Control-Plane in microseconds.
28+
std::chrono::microseconds T2a_max_cp_ul{500};
29+
/// T2a minimum parameter for uplink Control-Plane in microseconds.
30+
std::chrono::microseconds T2a_min_cp_ul{285};
31+
/// T2a maximum parameter for downlink User-Plane in microseconds.
32+
std::chrono::microseconds T2a_max_up{300};
33+
/// T2a minimum parameter for downlink User-Plane in microseconds.
34+
std::chrono::microseconds T2a_min_up{85};
2235
/// Ethernet network interface name or PCI bus identifier.
2336
std::string network_interface;
2437
/// RU emulator MAC address.
@@ -27,6 +40,8 @@ struct ru_emulator_ofh_appconfig {
2740
std::string du_mac_address;
2841
/// V-LAN Tag control information field.
2942
unsigned vlan_tag;
43+
/// Promiscuous mode flag.
44+
bool enable_promiscuous = false;
3045
/// RU Uplink ports.
3146
std::vector<unsigned> ru_ul_port_id = {0, 1};
3247
/// RU emulator operating bandwidth.

tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,26 @@ using namespace srsran;
1818

1919
static void configure_cli11_log_args(CLI::App& app, ru_emulator_log_appconfig& log_params)
2020
{
21-
auto level_check = [](const std::string& value) -> std::string {
22-
if (value == "info" || value == "debug" || value == "warning" || value == "error") {
21+
/// Function to check that the log level is correct.
22+
auto check_log_level = [](const std::string& value) -> std::string {
23+
if (srslog::str_to_basic_level(value).has_value()) {
2324
return {};
2425
}
25-
return "Log level value not supported. Accepted values [info,debug,warning,error]";
26+
27+
return fmt::format("Log level '{}' not supported. Accepted values [none,info,debug,warning,error]", value);
28+
};
29+
/// Function to convert string parameter to srslog level.
30+
auto capture_log_level_function = [](srslog::basic_levels& level) {
31+
return [&level](const std::string& value) {
32+
auto val = srslog::str_to_basic_level(value);
33+
level = (val) ? val.value() : srslog::basic_levels::none;
34+
};
2635
};
2736

2837
app.add_option("--filename", log_params.filename, "Log file output path")->capture_default_str();
29-
app.add_option("--level", log_params.level, "Log level")->capture_default_str()->check(level_check);
38+
add_option_function<std::string>(app, " --level", capture_log_level_function(log_params.level), "Log level")
39+
->default_str(srslog::basic_level_to_string(log_params.level))
40+
->check(check_log_level);
3041
}
3142

3243
static void configure_cli11_ru_emu_dpdk_args(CLI::App& app, std::optional<ru_emulator_dpdk_appconfig>& config)
@@ -71,7 +82,28 @@ static void configure_cli11_ru_emu_args(CLI::App& app, ru_emulator_ofh_appconfig
7182
app.add_option("--ru_mac_addr", config.ru_mac_address, "Radio Unit MAC address")->capture_default_str();
7283
app.add_option("--du_mac_addr", config.du_mac_address, "Distributed Unit MAC address")->capture_default_str();
7384
app.add_option("--vlan_tag", config.vlan_tag, "V-LAN identifier")->capture_default_str()->check(CLI::Range(1, 4094));
85+
app.add_option("--enable_promiscuous", config.enable_promiscuous, "Promiscuous mode flag")->capture_default_str();
7486
app.add_option("--ul_port_id", config.ru_ul_port_id, "RU uplink port identifier")->capture_default_str();
87+
88+
// Note: For the timing parameters, worst case is 2 slots for scs 15KHz and 14 symbols. Implementation defined.
89+
app.add_option("--t2a_max_cp_dl", config.T2a_max_cp_dl, "T2a maximum value for downlink Control-Plane")
90+
->capture_default_str()
91+
->check(CLI::Range(0, 1960));
92+
app.add_option("--t2a_min_cp_dl", config.T2a_min_cp_dl, "T2a minimum value for downlink Control-Plane")
93+
->capture_default_str()
94+
->check(CLI::Range(0, 1960));
95+
app.add_option("--t2a_max_cp_ul", config.T2a_max_cp_ul, "T2a maximum value for uplink Control-Plane")
96+
->capture_default_str()
97+
->check(CLI::Range(0, 1960));
98+
app.add_option("--t2a_min_cp_ul", config.T2a_min_cp_ul, "T2a minimum value for uplink Control-Plane")
99+
->capture_default_str()
100+
->check(CLI::Range(0, 1960));
101+
app.add_option("--t2a_max_up", config.T2a_max_up, "T2a maximum value for User-Plane")
102+
->capture_default_str()
103+
->check(CLI::Range(0, 1960));
104+
app.add_option("--t2a_min_up", config.T2a_min_up, "T2a minimum value for User-Plane")
105+
->capture_default_str()
106+
->check(CLI::Range(0, 1960));
75107
}
76108

77109
void srsran::configure_cli11_with_ru_emulator_appconfig_schema(CLI::App& app, ru_emulator_appconfig& ru_emu_parsed_cfg)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
*
3+
* Copyright 2021-2024 Software Radio Systems Limited
4+
*
5+
* By using this file, you agree to the terms and conditions set
6+
* forth in the LICENSE file which can be found at the top level of
7+
* the distribution.
8+
*
9+
*/
10+
11+
#include "ru_emulator_rx_window_checker.h"
12+
13+
using namespace srsran;
14+
using namespace ofh;
15+
16+
static constexpr unsigned OFH_MAX_NOF_SFN = 256U;
17+
18+
/// Calculates the Open Fronthaul slot symbol point for the given symbol point. An Open Fronthaul slot symbol point is a
19+
/// normal one, but with the SFN values restricted to 1 Byte.
20+
static slot_symbol_point calculate_ofh_slot_symbol_point(slot_symbol_point symbol_point)
21+
{
22+
// Build a new slot symbol point that manages that the SFN values in OFH is 1 byte.
23+
slot_point ota_slot = symbol_point.get_slot();
24+
slot_point ofh_slot(ota_slot.numerology(), ota_slot.sfn() % OFH_MAX_NOF_SFN, ota_slot.slot_index());
25+
26+
return {ofh_slot, symbol_point.get_symbol_index(), symbol_point.get_nof_symbols()};
27+
}
28+
29+
/// Calculate the distance between the given slot symbol points in symbols.
30+
static int calculate_slot_symbol_point_distance(slot_symbol_point lhs, slot_symbol_point rhs)
31+
{
32+
srsran_assert(rhs.get_numerology() == lhs.get_numerology(),
33+
"Cannot calculate the distance of two slot symbol points that have different numerologies");
34+
srsran_assert(rhs.get_nof_symbols() == lhs.get_nof_symbols(),
35+
"Cannot calculate the distance of two slot symbol points that have a different number of symbols");
36+
37+
const int nof_symbols_per_slot_wrap = OFH_MAX_NOF_SFN * NOF_SUBFRAMES_PER_FRAME *
38+
get_nof_slots_per_subframe(to_subcarrier_spacing(rhs.get_numerology())) *
39+
rhs.get_nof_symbols();
40+
41+
int a = static_cast<int>(lhs.to_uint()) - static_cast<int>(rhs.to_uint());
42+
if (a >= nof_symbols_per_slot_wrap / 2) {
43+
return a - nof_symbols_per_slot_wrap;
44+
}
45+
if (a < -nof_symbols_per_slot_wrap / 2) {
46+
return a + nof_symbols_per_slot_wrap;
47+
}
48+
return a;
49+
}
50+
51+
void ru_emulator_rx_window_checker::on_new_symbol(ofh::slot_symbol_point symbol_point)
52+
{
53+
// Build a new slot symbol point that manages that the SFN values in OFH is 1 byte.
54+
slot_symbol_point ota_symbol_point = calculate_ofh_slot_symbol_point(symbol_point);
55+
56+
// Update the stored slot symbol point as system value.
57+
count_val.store(ota_symbol_point.to_uint(), std::memory_order_release);
58+
}
59+
60+
void ru_emulator_rx_window_checker::update_rx_window_statistics(ofh::slot_symbol_point symbol_point)
61+
{
62+
// Store the ota symbol point to use the same value for the early and late points.
63+
slot_symbol_point ota_point(
64+
symbol_point.get_numerology(), count_val.load(std::memory_order_acquire), symbol_point.get_nof_symbols());
65+
66+
// Calculate the distance between the 2 slot symbol points in symbols.
67+
int diff = calculate_slot_symbol_point_distance(symbol_point, ota_point);
68+
69+
// Late detected.
70+
if (diff > static_cast<int>(timing_parameters.sym_end)) {
71+
statistics.increment_early_counter();
72+
return;
73+
}
74+
75+
// Early detected.
76+
if (diff < static_cast<int>(timing_parameters.sym_start)) {
77+
statistics.increment_late_counter();
78+
return;
79+
}
80+
81+
// On time detected.
82+
statistics.increment_on_time_counter();
83+
}
84+
85+
ru_emulator_rx_kpis ru_emulator_rx_window_checker::get_statistics()
86+
{
87+
return statistics.get_statistics();
88+
}
89+
90+
ru_emulator_rx_kpis ru_emulator_rx_window_checker::rx_window_checker_statistics::get_statistics()
91+
{
92+
ru_emulator_rx_kpis kpis;
93+
94+
// Fetch the data.
95+
uint64_t current_nof_on_time = nof_on_time_messages();
96+
uint64_t current_nof_late = nof_late_messages();
97+
uint64_t current_nof_early = nof_early_messages();
98+
99+
// Calculate the difference since last print.
100+
kpis.rx_on_time = current_nof_on_time - last_on_time_value_printed;
101+
kpis.rx_early = current_nof_early - last_early_value_printed;
102+
kpis.rx_late = current_nof_late - last_late_value_printed;
103+
104+
// Update last print.
105+
last_late_value_printed = current_nof_late;
106+
last_early_value_printed = current_nof_early;
107+
last_on_time_value_printed = current_nof_on_time;
108+
109+
return kpis;
110+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
*
3+
* Copyright 2021-2024 Software Radio Systems Limited
4+
*
5+
* By using this file, you agree to the terms and conditions set
6+
* forth in the LICENSE file which can be found at the top level of
7+
* the distribution.
8+
*
9+
*/
10+
11+
#pragma once
12+
13+
#include "srsran/ofh/receiver/ofh_receiver_timing_parameters.h"
14+
#include "srsran/ofh/timing/ofh_ota_symbol_boundary_notifier.h"
15+
#include "srsran/srslog/logger.h"
16+
#include <atomic>
17+
18+
namespace srsran {
19+
20+
/// Helper structure with aggregated reception window statistics.
21+
struct ru_emulator_rx_kpis {
22+
uint64_t rx_on_time;
23+
uint64_t rx_late;
24+
uint64_t rx_early;
25+
};
26+
27+
/// \brief Reception window checker.
28+
///
29+
/// Checks if the given slot and symbol is within the reception window or not and stores the statistics.
30+
class ru_emulator_rx_window_checker : public ofh::ota_symbol_boundary_notifier
31+
{
32+
/// Helper class that represents the reception window statistics.
33+
class rx_window_checker_statistics
34+
{
35+
std::atomic<uint64_t> on_time_counter{0};
36+
std::atomic<uint64_t> early_counter{0};
37+
std::atomic<uint64_t> late_counter{0};
38+
uint64_t last_on_time_value_printed = 0U;
39+
uint64_t last_early_value_printed = 0U;
40+
uint64_t last_late_value_printed = 0U;
41+
42+
public:
43+
/// Returns the statistics collected from the last time this function was called.
44+
ru_emulator_rx_kpis get_statistics();
45+
46+
/// Functions to increment the counters.
47+
void increment_on_time_counter() { on_time_counter.fetch_add(1, std::memory_order_relaxed); }
48+
void increment_early_counter() { early_counter.fetch_add(1, std::memory_order_relaxed); }
49+
void increment_late_counter() { late_counter.fetch_add(1, std::memory_order_relaxed); }
50+
51+
/// Getters to the message counters.
52+
uint64_t nof_on_time_messages() const { return on_time_counter.load(std::memory_order_relaxed); }
53+
uint64_t nof_early_messages() const { return early_counter.load(std::memory_order_relaxed); }
54+
uint64_t nof_late_messages() const { return late_counter.load(std::memory_order_relaxed); }
55+
};
56+
57+
const ofh::rx_window_timing_parameters timing_parameters;
58+
rx_window_checker_statistics statistics;
59+
std::atomic<uint32_t> count_val;
60+
61+
public:
62+
explicit ru_emulator_rx_window_checker(ofh::rx_window_timing_parameters params) : timing_parameters(params) {}
63+
64+
// See interface for documentation.
65+
void on_new_symbol(ofh::slot_symbol_point symbol_point) override;
66+
67+
/// Updates the Rx window statistics.
68+
void update_rx_window_statistics(ofh::slot_symbol_point symbol_point);
69+
70+
/// Getters to the number of messages.
71+
uint64_t nof_on_time_messages() const { return statistics.nof_on_time_messages(); }
72+
uint64_t nof_early_messages() const { return statistics.nof_early_messages(); }
73+
uint64_t nof_late_messages() const { return statistics.nof_late_messages(); }
74+
75+
/// Returns the statistics collected from the last time this function was called.
76+
ru_emulator_rx_kpis get_statistics();
77+
};
78+
79+
} // namespace srsran

0 commit comments

Comments
 (0)