From af8898943f2f1dc901175795b7a96aa299a21de2 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 25 Aug 2020 18:07:56 +0200 Subject: [PATCH] SRSENB: implement console cell_gain command SRSENB: fix 5GNR compilation SRSENB: fix override methods --- .../srslte/interfaces/enb_command_interface.h | 40 +++++++++++++++++ srsenb/hdr/enb.h | 12 +++--- srsenb/hdr/phy/enb_phy_base.h | 2 + srsenb/hdr/phy/phy.h | 2 + srsenb/hdr/phy/phy_common.h | 15 +++++++ srsenb/hdr/phy/phy_interfaces.h | 1 + srsenb/hdr/phy/vnf_phy_nr.h | 17 +++++--- srsenb/src/enb.cc | 5 +++ srsenb/src/main.cc | 43 +++++++++++++------ srsenb/src/phy/cc_worker.cc | 10 +++++ srsenb/src/phy/phy.cc | 5 +++ 11 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 lib/include/srslte/interfaces/enb_command_interface.h diff --git a/lib/include/srslte/interfaces/enb_command_interface.h b/lib/include/srslte/interfaces/enb_command_interface.h new file mode 100644 index 000000000..e30182465 --- /dev/null +++ b/lib/include/srslte/interfaces/enb_command_interface.h @@ -0,0 +1,40 @@ +/* + * 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/. + * + */ + +#ifndef SRSLTE_ENB_COMMAND_INTERFACE_H +#define SRSLTE_ENB_COMMAND_INTERFACE_H + +#include + +namespace srsenb { +class enb_command_interface +{ +public: + /** + * Sets the relative gain of a cell from it's index (following rr.conf) order. + * @param cell_idx Provides a cell index + * @param gain Relative gain + */ + virtual void cmd_cell_gain(uint32_t cell_idx, float gain) = 0; +}; +} // namespace srsenb + +#endif // SRSLTE_ENB_COMMAND_INTERFACE_H diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 8fd4a4437..99e56db08 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -47,6 +47,7 @@ #include "srslte/common/log_filter.h" #include "srslte/common/mac_pcap.h" #include "srslte/common/security.h" +#include "srslte/interfaces/enb_command_interface.h" #include "srslte/interfaces/enb_metrics_interface.h" #include "srslte/interfaces/sched_interface.h" #include "srslte/interfaces/ue_interfaces.h" @@ -111,7 +112,7 @@ struct all_args_t { Main eNB class *******************************************************************************/ -class enb : public enb_metrics_interface +class enb : public enb_metrics_interface, enb_command_interface { public: enb(); @@ -126,12 +127,11 @@ public: void print_pool(); - static void rf_msg(srslte_rf_error_t error); - - void handle_rf_msg(srslte_rf_error_t error); - // eNodeB metrics interface - bool get_metrics(enb_metrics_t* m); + bool get_metrics(enb_metrics_t* m) override; + + // eNodeB command interface + void cmd_cell_gain(uint32_t cell_idx, float gain) override; private: const static int ENB_POOL_SIZE = 1024 * 10; diff --git a/srsenb/hdr/phy/enb_phy_base.h b/srsenb/hdr/phy/enb_phy_base.h index 794fbeee8..3daf32965 100644 --- a/srsenb/hdr/phy/enb_phy_base.h +++ b/srsenb/hdr/phy/enb_phy_base.h @@ -44,6 +44,8 @@ public: virtual void start_plot() = 0; virtual void get_metrics(phy_metrics_t* m) = 0; + + virtual void cmd_cell_gain(uint32_t cell_idx, float gain_db) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 255d68e0e..2ee849d17 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -68,6 +68,8 @@ public: void get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) override; + void cmd_cell_gain(uint32_t cell_idx, float gain_db) override; + void radio_overflow() override{}; void radio_failure() override{}; diff --git a/srsenb/hdr/phy/phy_common.h b/srsenb/hdr/phy/phy_common.h index 72bc96eec..2c009a254 100644 --- a/srsenb/hdr/phy/phy_common.h +++ b/srsenb/hdr/phy/phy_common.h @@ -137,6 +137,21 @@ public: return c; }; + void set_cell_gain(uint32_t cc_idx, float gain_db) + { + if (cc_idx < cell_list.size()) { + cell_list.at(cc_idx).gain_db = gain_db; + } + } + + float get_cell_gain(uint32_t cc_idx) + { + if (cc_idx < cell_list.size()) { + return cell_list.at(cc_idx).gain_db; + } + return 0.0f; + } + // Common Physical Uplink DMRS configuration srslte_refsignal_dmrs_pusch_cfg_t dmrs_pusch_cfg = {}; diff --git a/srsenb/hdr/phy/phy_interfaces.h b/srsenb/hdr/phy/phy_interfaces.h index 7ff1dfa7f..93491fa96 100644 --- a/srsenb/hdr/phy/phy_interfaces.h +++ b/srsenb/hdr/phy/phy_interfaces.h @@ -38,6 +38,7 @@ struct phy_cell_cfg_t { double ul_freq_hz; uint32_t root_seq_idx; uint32_t num_ra_preambles; + float gain_db; }; typedef std::vector phy_cell_cfg_list_t; diff --git a/srsenb/hdr/phy/vnf_phy_nr.h b/srsenb/hdr/phy/vnf_phy_nr.h index efdb30798..d225d5b92 100644 --- a/srsenb/hdr/phy/vnf_phy_nr.h +++ b/srsenb/hdr/phy/vnf_phy_nr.h @@ -44,17 +44,22 @@ public: ~vnf_phy_nr(); int init(const srsenb::phy_args_t& args, const nr_phy_cfg_t& cfg, srsenb::stack_interface_phy_nr* stack_); - void stop(); + void stop() override; - std::string get_type() { return "vnf"; }; + std::string get_type() override { return "vnf"; }; - void start_plot(); + void start_plot() override; - void get_metrics(srsenb::phy_metrics_t metrics[ENB_METRICS_MAX_USERS]); + void get_metrics(srsenb::phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) override; // MAC interface - int dl_config_request(const dl_config_request_t& request); - int tx_request(const tx_request_t& request); + int dl_config_request(const dl_config_request_t& request) override; + int tx_request(const tx_request_t& request) override; + + void cmd_cell_gain(uint32_t cell_idx, float gain_db) override + { + // Do nothing + } private: srslte::logger* logger = nullptr; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index b48204e23..7a4f1c416 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -211,6 +211,11 @@ bool enb::get_metrics(enb_metrics_t* m) return true; } +void enb::cmd_cell_gain(uint32_t cell_idx, float gain) +{ + phy->cmd_cell_gain(cell_idx, gain); +} + srslte::LOG_LEVEL_ENUM enb::level(std::string l) { std::transform(l.begin(), l.end(), l.begin(), ::toupper); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 39b3b7775..e69e34305 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "srsenb/hdr/enb.h" @@ -150,7 +151,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("channel.dl.awgn.enable", bpo::value(&args->phy.dl_channel_args.awgn_enable)->default_value(false), "Enable/Disable AWGN simulator") ("channel.dl.awgn.snr", bpo::value(&args->phy.dl_channel_args.awgn_snr_dB)->default_value(30.0f), "Noise level in decibels full scale (dBfs)") ("channel.dl.fading.enable", bpo::value(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") - ("channel.dl.fading.model", bpo::value(&args->phy.dl_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") + ("channel.dl.fading.model", bpo::value(&args->phy.dl_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.dl.delay.enable", bpo::value(&args->phy.dl_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") ("channel.dl.delay.period_s", bpo::value(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") ("channel.dl.delay.init_time_s", bpo::value(&args->phy.dl_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") @@ -170,7 +171,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("channel.ul.awgn.signal_power", bpo::value(&args->phy.ul_channel_args.awgn_signal_power_dBfs)->default_value(30.0f), "Received signal power in decibels full scale (dBfs)") ("channel.ul.awgn.snr", bpo::value(&args->phy.ul_channel_args.awgn_snr_dB)->default_value(30.0f), "Noise level in decibels full scale (dBfs)") ("channel.ul.fading.enable", bpo::value(&args->phy.ul_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") - ("channel.ul.fading.model", bpo::value(&args->phy.ul_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") + ("channel.ul.fading.model", bpo::value(&args->phy.ul_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.ul.delay.enable", bpo::value(&args->phy.ul_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") ("channel.ul.delay.period_s", bpo::value(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") ("channel.ul.delay.init_time_s", bpo::value(&args->phy.ul_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") @@ -398,17 +399,18 @@ void parse_args(all_args_t* args, int argc, char* argv[]) static bool do_metrics = false; -void* input_loop(void* m) +static void* input_loop(metrics_stdout* metrics, srsenb::enb_command_interface* control) { - metrics_stdout* metrics = (metrics_stdout*)m; - char key; + string input_line; while (running) { - cin >> key; + getline(cin, input_line); if (cin.eof() || cin.bad()) { cout << "Closing stdin thread." << endl; break; - } else { - if ('t' == key) { + } else if (not input_line.empty()) { + vector cmd; + srslte::string_parse_list(input_line, ' ', cmd); + if (cmd[0] == "t") { do_metrics = !do_metrics; if (do_metrics) { cout << "Enter t to stop trace." << endl; @@ -416,8 +418,26 @@ void* input_loop(void* m) cout << "Enter t to restart trace." << endl; } metrics->toggle_print(do_metrics); - } else if ('q' == key) { + } else if (cmd[0] == "q") { raise(SIGTERM); + } else if (cmd[0] == "cell_gain") { + if (cmd.size() != 3) { + cout << "Usage: " << cmd[0] << " [cell index] [gain in dB]" << endl; + continue; + } + + // Parse command arguments + uint32_t cell_idx = srslte::string_cast(cmd[1]); + float gain_db = srslte::string_cast(cmd[2]); + + // Set cell gain + control->cmd_cell_gain(cell_idx, gain_db); + } else { + cout << "Available commands: " << endl; + cout << " t: starts console trace" << endl; + cout << " q: quit srsenb" << endl; + cout << " cell_gain: set relative cell gain" << endl; + cout << endl; } } } @@ -484,8 +504,7 @@ int main(int argc, char* argv[]) } // create input thread - pthread_t input; - pthread_create(&input, nullptr, &input_loop, &metrics_screen); + thread input(&input_loop, &metrics_screen, (enb_command_interface*)enb.get()); bool signals_pregenerated = false; if (running) { @@ -504,8 +523,6 @@ int main(int argc, char* argv[]) } usleep(10000); } - pthread_cancel(input); - pthread_join(input, NULL); metricshub.stop(); enb->stop(); cout << "--- exiting ---" << endl; diff --git a/srsenb/src/phy/cc_worker.cc b/srsenb/src/phy/cc_worker.cc index ebd694e0d..84420a502 100644 --- a/srsenb/src/phy/cc_worker.cc +++ b/srsenb/src/phy/cc_worker.cc @@ -266,6 +266,16 @@ void cc_worker::work_dl(const srslte_dl_sf_cfg_t& dl_sf_cfg, // Generate signal and transmit srslte_enb_dl_gen_signal(&enb_dl); + + // Scale if cell gain is set + float cell_gain_db = phy->get_cell_gain(cc_idx); + if (std::isnormal(cell_gain_db)) { + float scale = srslte_convert_dB_to_amplitude(cell_gain_db); + uint32_t sf_len = SRSLTE_SF_LEN_PRB(enb_dl.cell.nof_prb); + for (uint32_t i = 0; i < enb_dl.cell.nof_ports; i++) { + srslte_vec_sc_prod_cfc(signal_buffer_tx[i], scale, signal_buffer_tx[i], sf_len); + } + } } void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_grant, diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 48ef3d021..c41a2ce16 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -220,6 +220,11 @@ void phy::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) } } +void phy::cmd_cell_gain(uint32_t cc_idx, float gain_db) +{ + workers_common.set_cell_gain(cc_idx, gain_db); +} + /***** RRC->PHY interface **********/ void phy::set_config(uint16_t rnti, const phy_rrc_cfg_list_t& phy_cfg_list)