Skip to content

Commit 2981269

Browse files
test: add simple benchmark for UDP gateway
1 parent 4177d03 commit 2981269

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed

tests/benchmarks/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ remove_definitions(-DASSERTS_ENABLED)
1010
remove_definitions(-DPARANOID_ASSERTS_ENABLED)
1111

1212
add_subdirectory(adt)
13+
add_subdirectory(gateways)
1314
add_subdirectory(phy)
1415
add_subdirectory(scheduler)
1516
add_subdirectory(du_high)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#
2+
# Copyright 2021-2023 Software Radio Systems Limited
3+
#
4+
# By using this file, you agree to the terms and conditions set
5+
# forth in the LICENSE file which can be found at the top level of
6+
# the distribution.
7+
#
8+
9+
set_directory_properties(PROPERTIES LABELS "gateways")
10+
11+
include_directories(../../..)
12+
13+
add_executable(udp_network_gateway_benchmark udp_network_gateway_benchmark.cpp)
14+
target_link_libraries(udp_network_gateway_benchmark srsran_network srsran_gateway srsran_support srslog)
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
*
3+
* Copyright 2021-2023 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 "srsran/gateways/udp_network_gateway_factory.h"
12+
#include "srsran/srslog/srslog.h"
13+
#include "srsran/support/io/io_broker_factory.h"
14+
#include <arpa/inet.h>
15+
#include <getopt.h>
16+
#include <queue>
17+
18+
using namespace srsran;
19+
20+
struct bench_params {
21+
unsigned nof_repetitions = 100;
22+
};
23+
24+
static void usage(const char* prog, const bench_params& params)
25+
{
26+
fmt::print("Usage: {} [-R repetitions] [-s silent]\n", prog);
27+
fmt::print("\t-R Repetitions [Default {}]\n", params.nof_repetitions);
28+
fmt::print("\t-h Show this message\n");
29+
}
30+
31+
static void parse_args(int argc, char** argv, bench_params& params)
32+
{
33+
int opt = 0;
34+
while ((opt = getopt(argc, argv, "R:h")) != -1) {
35+
switch (opt) {
36+
case 'R':
37+
params.nof_repetitions = std::strtol(optarg, nullptr, 10);
38+
break;
39+
case 'h':
40+
default:
41+
usage(argv[0], params);
42+
exit(0);
43+
}
44+
}
45+
}
46+
47+
class dummy_network_gateway_data_notifier_with_src_addr : public network_gateway_data_notifier_with_src_addr
48+
{
49+
public:
50+
dummy_network_gateway_data_notifier_with_src_addr() = default;
51+
void on_new_pdu(byte_buffer pdu, const sockaddr_storage& src_addr) override
52+
{
53+
rx_bytes += pdu.length();
54+
n_pdus++;
55+
}
56+
57+
unsigned get_rx_bytes() { return rx_bytes; }
58+
unsigned get_n_pdus() { return n_pdus; }
59+
60+
private:
61+
unsigned rx_bytes = 0;
62+
unsigned n_pdus = 0;
63+
};
64+
65+
byte_buffer make_tx_byte_buffer(uint32_t length)
66+
{
67+
byte_buffer pdu{};
68+
for (uint32_t i = 0; i < length; ++i) {
69+
pdu.append((uint8_t)i);
70+
}
71+
return pdu;
72+
}
73+
74+
byte_buffer make_default_byte_buffer()
75+
{
76+
return make_tx_byte_buffer(1400);
77+
}
78+
79+
sockaddr_storage to_sockaddr_storage(std::string dest_addr, uint16_t port)
80+
{
81+
in_addr inaddr_v4 = {};
82+
in6_addr inaddr_v6 = {};
83+
sockaddr_storage addr_storage = {};
84+
85+
if (inet_pton(AF_INET, dest_addr.c_str(), &inaddr_v4) == 1) {
86+
sockaddr_in* tmp = (sockaddr_in*)&addr_storage;
87+
tmp->sin_family = AF_INET;
88+
tmp->sin_addr = inaddr_v4;
89+
tmp->sin_port = htons(port);
90+
} else if (inet_pton(AF_INET6, dest_addr.c_str(), &inaddr_v6) == 1) {
91+
sockaddr_in6* tmp = (sockaddr_in6*)&addr_storage;
92+
tmp->sin6_family = AF_INET6;
93+
tmp->sin6_addr = inaddr_v6;
94+
tmp->sin6_port = htons(port);
95+
}
96+
return addr_storage;
97+
}
98+
99+
int main(int argc, char** argv)
100+
{
101+
srslog::init();
102+
103+
// init GW logger
104+
srslog::fetch_basic_logger("UDP-GW", true).set_level(srslog::basic_levels::warning);
105+
srslog::fetch_basic_logger("UDP-GW", true).set_hex_dump_max_size(100);
106+
107+
bench_params params{};
108+
parse_args(argc, argv, params);
109+
110+
udp_network_gateway_config gw1_cfg;
111+
gw1_cfg.bind_address = "127.0.0.1";
112+
gw1_cfg.bind_port = 56701;
113+
gw1_cfg.non_blocking_mode = true;
114+
115+
udp_network_gateway_config gw2_cfg;
116+
gw2_cfg.bind_address = "127.0.0.1";
117+
gw2_cfg.bind_port = 56702;
118+
gw2_cfg.non_blocking_mode = true;
119+
120+
dummy_network_gateway_data_notifier_with_src_addr gw1_dn, gw2_dn;
121+
std::unique_ptr<udp_network_gateway> gw1, gw2;
122+
123+
gw1 = create_udp_network_gateway({gw1_cfg, gw1_dn});
124+
gw2 = create_udp_network_gateway({gw2_cfg, gw2_dn});
125+
126+
gw1->create_and_bind();
127+
gw2->create_and_bind();
128+
129+
std::unique_ptr<io_broker> epoll_broker;
130+
131+
epoll_broker = create_io_broker(io_broker_type::epoll);
132+
133+
epoll_broker->register_fd(gw1->get_socket_fd(), [&gw1](int fd) { gw1->receive(); });
134+
epoll_broker->register_fd(gw2->get_socket_fd(), [&gw2](int fd) { gw2->receive(); });
135+
136+
sockaddr_storage gw2_addr = to_sockaddr_storage(gw2_cfg.bind_address, gw2_cfg.bind_port);
137+
138+
byte_buffer pdu = make_default_byte_buffer();
139+
140+
auto t_start = std::chrono::high_resolution_clock::now();
141+
142+
unsigned N = 100000;
143+
for (unsigned n = 0; n < N; n++) {
144+
gw1->handle_pdu(pdu, gw2_addr);
145+
}
146+
auto t_end = std::chrono::high_resolution_clock::now();
147+
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t_end - t_start);
148+
149+
std::this_thread::sleep_for(std::chrono::milliseconds(250));
150+
151+
fmt::print("Tx time: {} us\n", duration.count());
152+
fmt::print("Tx data rate: {:.2f} Mbit/s\n\n", (double)pdu.length() * N * 8 * 1e-6 / (duration.count() * 1e-6));
153+
fmt::print("Tx PDU rate: {:.2f} PDU/s\n", (double)N / (duration.count() * 1e-6));
154+
fmt::print("Rx PDU rate: {:.2f} PDU/s\n\n", (double)gw2_dn.get_n_pdus() / (duration.count() * 1e-6));
155+
fmt::print("Tx PDUs total: {:>7}\n", N);
156+
fmt::print("Rx PDUs total: {:>7}\n", gw2_dn.get_n_pdus());
157+
}

0 commit comments

Comments
 (0)