diff --git a/lib/test/common/CMakeLists.txt b/lib/test/common/CMakeLists.txt index 8b73dee43..646076e50 100644 --- a/lib/test/common/CMakeLists.txt +++ b/lib/test/common/CMakeLists.txt @@ -101,5 +101,8 @@ add_test(expected_test expected_test) if(ENABLE_5GNR) add_executable(pnf_dummy pnf_dummy.cc) target_link_libraries(pnf_dummy ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) + + add_executable(pnf_bridge pnf_bridge.cc) + target_link_libraries(pnf_bridge ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) endif() diff --git a/lib/test/common/pnf_bridge.cc b/lib/test/common/pnf_bridge.cc new file mode 100644 index 000000000..8fc8e8404 --- /dev/null +++ b/lib/test/common/pnf_bridge.cc @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/common/basic_pnf.h" + +using namespace std; +namespace bpo = boost::program_options; + +struct pnf_args_t { + std::string gnb_vnf_addr; + std::string ue_vnf_addr; + uint16_t gnb_vnf_port; + uint16_t ue_vnf_port; + uint32_t sf_interval; + int32_t num_sf; + uint32_t tb_len; +}; + +void parse_args(pnf_args_t* args, int argc, char* argv[]) +{ + // Command line only options + bpo::options_description general("General options"); + + general.add_options()("help,h", "Produce help message")("version,v", "Print version information and exit"); + + // Command line or config file options + bpo::options_description common("Configuration options"); + + // clang-format off + common.add_options() + ("vnf.gnb_addr", bpo::value(&args->gnb_vnf_addr)->default_value("127.0.0.1"), "VNF address") + ("vnf.ue_addr", bpo::value(&args->ue_vnf_addr)->default_value("127.0.0.1"), "VNF address") + ("vnf.gnb_port", bpo::value(&args->gnb_vnf_port)->default_value(3333), "gNB VNF port") + ("vnf.ue_port", bpo::value(&args->ue_vnf_port)->default_value(3334), "UE VNF port") + ("sf_interval", bpo::value(&args->sf_interval)->default_value(1000), "Interval between subframes in us") + ("num_sf", bpo::value(&args->num_sf)->default_value(-1), "Number of subframes to signal (-1 infinity)") + ("tb_len", bpo::value(&args->tb_len)->default_value(0), "TB lenth (0 for random size)"); + // clang-format on + + // these options are allowed on the command line + bpo::options_description cmdline_options; + cmdline_options.add(common).add(general); + + // parse the command line and store result in vm + bpo::variables_map vm; + bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm); + bpo::notify(vm); + + // help option was given - print usage and exit + if (vm.count("help")) { + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + cout << common << endl << general << endl; + exit(0); + } +} + +bool running = true; +void sig_int_handler(int signo) +{ + printf("SIGINT received. Exiting...\n"); + if (signo == SIGINT) { + running = false; + } +} + +int main(int argc, char** argv) +{ + signal(SIGINT, sig_int_handler); + + pnf_args_t args; + parse_args(&args, argc, argv); + + srslte::srslte_basic_pnf ue_pnf("ue", args.ue_vnf_addr, args.ue_vnf_port, args.sf_interval, args.num_sf, args.tb_len); + srslte::srslte_basic_pnf gnb_pnf( + "gnb", args.gnb_vnf_addr, args.gnb_vnf_port, args.sf_interval, args.num_sf, args.tb_len); + + ue_pnf.start(); + gnb_pnf.start(); + + while (running) { + for (uint32_t i = 0; i < 2; ++i) { + srslte::pnf_metrics_t metrics = (i == 0) ? ue_pnf.get_metrics() : gnb_pnf.get_metrics(); + printf("%s: RTT=%d, #Error=%d, #PDUs=%d, Total TB size=%d, Rate=%.2f Mbit/s\n", + i == 0 ? "UE" : "gNB", + metrics.avg_rtt_us, + metrics.num_timing_errors, + metrics.num_pdus, + metrics.tb_size, + metrics.tb_size * 8 / 1e6); + } + + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + ue_pnf.stop(); + gnb_pnf.stop(); + + return 0; +} \ No newline at end of file