From 64b7dfed657494bd05c53209e9cf1a6a5f2be8ce Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 5 Jul 2021 16:46:03 +0200 Subject: [PATCH 01/59] UHD: fix nullptr buffer --- lib/src/phy/rf/rf_uhd_imp.cc | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.cc b/lib/src/phy/rf/rf_uhd_imp.cc index b9447f415..4443f3603 100644 --- a/lib/src/phy/rf/rf_uhd_imp.cc +++ b/lib/src/phy/rf/rf_uhd_imp.cc @@ -20,6 +20,7 @@ #include "rf_helper.h" #include "srsran/phy/utils/debug.h" +#include "srsran/phy/utils/vector.h" #include "rf_uhd_generic.h" #include "rf_uhd_imp.h" @@ -188,7 +189,8 @@ void suppress_handler(const char* x) // do nothing } -static cf_t zero_mem[64 * 1024] = {}; +static std::array zero_mem = {}; // For transmitting zeros +static std::array dummy_mem = {}; // For receiving static void log_overflow(rf_uhd_handler_t* h) { @@ -554,13 +556,14 @@ void rf_uhd_flush_buffer(void* h) // Set all pointers to zero buffer for (auto& i : data) { - i = zero_mem; + i = dummy_mem.data(); } // Receive until time out uhd::rx_metadata_t md; do { - if (handler->uhd->receive(data, handler->rx_nof_samples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) { + uint32_t nsamples = SRSRAN_MIN(handler->rx_nof_samples, (uint32_t)dummy_mem.size()); + if (handler->uhd->receive(data, nsamples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) { log_rx_error(handler); return; } @@ -949,7 +952,7 @@ static inline int rf_uhd_imp_end_burst(rf_uhd_handler_t* handler) // Set buffer pointers for (int i = 0; i < SRSRAN_MAX_CHANNELS; i++) { - buffs_ptr[i] = zero_mem; + buffs_ptr[i] = zero_mem.data(); } // Set metadata @@ -1261,13 +1264,19 @@ int rf_uhd_recv_with_time_multi(void* h, // Receive stream in multiple blocks while (rxd_samples_total < nsamples and trials < RF_UHD_IMP_MAX_RX_TRIALS) { void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {}; - for (uint32_t i = 0; i < handler->nof_rx_channels; i++) { - cf_t* data_c = (cf_t*)data[i]; - buffs_ptr[i] = &data_c[rxd_samples_total]; - } size_t num_samps_left = nsamples - rxd_samples_total; - size_t num_rx_samples = (num_samps_left > handler->rx_nof_samples) ? handler->rx_nof_samples : num_samps_left; + size_t num_rx_samples = SRSRAN_MIN(handler->rx_nof_samples, num_samps_left); + + for (uint32_t i = 0; i < handler->nof_rx_channels; i++) { + if (data[i] != nullptr) { + cf_t* data_c = (cf_t*)data[i]; + buffs_ptr[i] = &data_c[rxd_samples_total]; + } else { + buffs_ptr[i] = dummy_mem.data(); + num_rx_samples = SRSRAN_MIN(num_rx_samples, (uint32_t)dummy_mem.size()); + } + } if (handler->uhd->receive(buffs_ptr, num_rx_samples, md, 1.0, false, rxd_samples) != UHD_ERROR_NONE) { log_rx_error(handler); @@ -1379,9 +1388,9 @@ int rf_uhd_send_timed_multi(void* h, cf_t* data_c[SRSRAN_MAX_CHANNELS] = {}; for (uint32_t i = 0; i < SRSRAN_MAX_CHANNELS; i++) { if (i < handler->nof_tx_channels) { - data_c[i] = (data[i] != nullptr) ? (cf_t*)(data[i]) : zero_mem; + data_c[i] = (data[i] != nullptr) ? (cf_t*)(data[i]) : zero_mem.data(); } else { - data_c[i] = zero_mem; + data_c[i] = zero_mem.data(); } } From 96cb25b8685b1f436313fa4731281113a7cb27be Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 6 Jul 2021 18:26:33 +0200 Subject: [PATCH 02/59] Add arguments to NR PHY test --- srsenb/hdr/phy/nr/worker_pool.h | 10 +-- srsenb/src/phy/nr/worker_pool.cc | 6 +- test/phy/CMakeLists.txt | 4 +- test/phy/dummy_gnb_stack.h | 63 +++++++++------- test/phy/nr_phy_test.cc | 123 ++++++++++++++++++++++--------- test/phy/test_bench.h | 47 +++++++----- 6 files changed, 166 insertions(+), 87 deletions(-) diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 5d648efbf..580aa22fe 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -31,12 +31,10 @@ class worker_pool public: struct args_t { - uint32_t nof_phy_threads = 3; - uint32_t prio = 52; - std::string log_level = "info"; - uint32_t log_hex_limit = 64; - std::string log_id_preamble = ""; - uint32_t pusch_max_nof_iter = 10; + uint32_t nof_phy_threads = 3; + uint32_t prio = 52; + uint32_t pusch_max_nof_iter = 10; + srsran::phy_log_args_t log = {}; }; slot_worker* operator[](std::size_t pos) { return workers.at(pos).get(); } diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index b2a16999f..d0de0be3b 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -26,11 +26,11 @@ worker_pool::worker_pool(srsran::phy_common_interface& common_, bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list) { // Add workers to workers pool and start threads - srslog::basic_levels log_level = srslog::str_to_basic_level(args.log_level); + srslog::basic_levels log_level = srslog::str_to_basic_level(args.log.phy_level); for (uint32_t i = 0; i < args.nof_phy_threads; i++) { - auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log_id_preamble, i), log_sink); + auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log.id_preamble, i), log_sink); log.set_level(log_level); - log.set_hex_dump_max_size(args.log_hex_limit); + log.set_hex_dump_max_size(args.log.phy_hex_limit); auto w = new slot_worker(common, stack, log); pool.init_worker(i, w, args.prio); diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index ea235b828..0e4f0f627 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -21,5 +21,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) - add_nr_test(nr_phy_test nr_phy_test) + add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pusch.slots="") + add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots="") + add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test --duration=100) endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index d1069dd1d..880625342 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -16,10 +16,12 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" #include +#include #include #include #include #include +#include #include class gnb_dummy_stack : public srsenb::stack_interface_phy_nr @@ -33,12 +35,12 @@ private: srsran::circular_array dl_data_to_ul_ack; uint32_t ss_id = 0; uint32_t dl_freq_res = 0; - uint32_t dl_time_res = 0; uint32_t ul_freq_res = 0; - uint32_t ul_time_res = 0; srsran_random_t random_gen = nullptr; srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; + std::set dl_slots; + std::set ul_slots; std::mutex mac_metrics_mutex; srsenb::mac_ue_metrics_t mac_metrics = {}; @@ -118,6 +120,10 @@ private: bool schedule_pdsch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { + if (dl_slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx)) == 0) { + return true; + } + // Instantiate PDCCH and PDSCH pdcch_dl_t pdcch = {}; pdsch_t pdsch = {}; @@ -140,7 +146,7 @@ private: // Fill DCI fields srsran_dci_dl_nr_t& dci = pdcch.dci; dci.freq_domain_assigment = dl_freq_res; - dci.time_domain_assigment = dl_time_res; + dci.time_domain_assigment = 0; dci.mcs = mcs; dci.rv = 0; dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; @@ -192,6 +198,10 @@ private: bool schedule_pusch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { + if (ul_slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx + 4)) == 0) { + return true; + } + // Instantiate PDCCH pdcch_ul_t pdcch = {}; @@ -207,7 +217,7 @@ private: // Fill DCI fields srsran_dci_ul_nr_t& dci = pdcch.dci; dci.freq_domain_assigment = ul_freq_res; - dci.time_domain_assigment = ul_time_res; + dci.time_domain_assigment = 0; dci.freq_hopping_flag = 0; dci.mcs = mcs; dci.rv = 0; @@ -255,27 +265,30 @@ private: public: struct args_t { - srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - uint16_t rnti = 0x1234; ///< C-RNTI - uint32_t mcs = 10; ///< Modulation code scheme - uint32_t ss_id = 1; ///< Search Space identifier - uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level - uint32_t pdcch_dl_candidate_index = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate_index = 1; ///< PDCCH UL DCI candidate index - uint32_t dl_start_rb = 0; ///< Start resource block - uint32_t dl_length_rb = 0; ///< Number of resource blocks - uint32_t ul_start_rb = 0; ///< Start resource block - uint32_t ul_length_rb = 0; ///< Number of resource blocks - uint32_t dl_time_res = 0; ///< PDSCH time resource - std::string log_level = "debug"; + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t mcs = 10; ///< Modulation code scheme + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index + uint32_t dl_start_rb = 0; ///< Start resource block + uint32_t dl_length_rb = 0; ///< Number of resource blocks + std::string dl_sched_slots = "0,1,2,3,4,5"; ///< PDCH Slot list + uint32_t ul_start_rb = 0; ///< Start resource block + uint32_t ul_length_rb = 0; ///< Number of resource blocks + std::string ul_sched_slots = "6,7,8,9"; ///< Slot list + std::string log_level = "warning"; }; - gnb_dummy_stack(args_t args) : - mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id) + gnb_dummy_stack(const args_t& args) : mcs(args.mcs), rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); logger.set_level(srslog::str_to_basic_level(args.log_level)); + srsran::string_parse_list(args.dl_sched_slots, ',', dl_slots); + srsran::string_parse_list(args.ul_sched_slots, ',', ul_slots); + // Select DCI locations for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { srsran::bounded_vector locations; @@ -287,24 +300,24 @@ public: } // DCI DL - if (args.pdcch_dl_candidate_index >= locations.size()) { + if (args.pdcch_dl_candidate >= locations.size()) { logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", - args.pdcch_dl_candidate_index, + args.pdcch_dl_candidate, (uint32_t)locations.size(), args.pdcch_aggregation_level); return; } - dci_dl_location[slot] = locations[args.pdcch_dl_candidate_index]; + dci_dl_location[slot] = locations[args.pdcch_dl_candidate]; // DCI UL - if (args.pdcch_ul_candidate_index >= locations.size()) { + if (args.pdcch_ul_candidate >= locations.size()) { logger.error("Candidate index %d exceeds the number of candidates %d for aggregation level %d", - args.pdcch_ul_candidate_index, + args.pdcch_ul_candidate, (uint32_t)locations.size(), args.pdcch_aggregation_level); return; } - dci_ul_location[slot] = locations[args.pdcch_ul_candidate_index]; + dci_ul_location[slot] = locations[args.pdcch_ul_candidate]; } // Select DL frequency domain resources diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 151105178..df570516f 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -15,11 +15,77 @@ #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/test_common.h" #include "test_bench.h" +#include +#include + +// shorten boost program options namespace +namespace bpo = boost::program_options; test_bench::args_t::args_t(int argc, char** argv) { - // Flag configuration as valid - valid = true; + bpo::options_description options("Test bench options"); + bpo::options_description options_gnb_stack("gNb stack and scheduling related options"); + bpo::options_description options_gnb_phy("gNb PHY related options"); + bpo::options_description options_ue_stack("UE stack options"); + bpo::options_description options_ue_phy("UE stack options"); + + uint16_t rnti = 0x1234; + + // clang-format off + options.add_options() + ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") + ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") + ; + + options_gnb_stack.add_options() + ("gnb.stack.pdcch.aggregation_level", bpo::value(&gnb_stack.pdcch_aggregation_level)->default_value(gnb_stack.pdcch_aggregation_level), "PDCCH aggregation level") + ("gnb.stack.pdsch.candidate", bpo::value(&gnb_stack.pdcch_dl_candidate)->default_value(gnb_stack.pdcch_dl_candidate), "PDCCH candidate index for PDSCH") + ("gnb.stack.pdsch.start", bpo::value(&gnb_stack.dl_start_rb)->default_value(0), "PDSCH scheduling frequency allocation start") + ("gnb.stack.pdsch.length", bpo::value(&gnb_stack.dl_length_rb)->default_value(gnb_stack.dl_length_rb), "PDSCH scheduling frequency allocation length") + ("gnb.stack.pdsch.slots", bpo::value(&gnb_stack.dl_sched_slots)->default_value(gnb_stack.dl_sched_slots), "Slots enabled for PDSCH") + ("gnb.stack.pusch.candidate", bpo::value(&gnb_stack.pdcch_ul_candidate)->default_value(gnb_stack.pdcch_ul_candidate), "PDCCH candidate index for PUSCH") + ("gnb.stack.pusch.start", bpo::value(&gnb_stack.ul_start_rb)->default_value(0), "PUSCH scheduling frequency allocation start") + ("gnb.stack.pusch.length", bpo::value(&gnb_stack.ul_length_rb)->default_value(gnb_stack.ul_length_rb), "PUSCH scheduling frequency allocation length") + ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.ul_sched_slots)->default_value(gnb_stack.ul_sched_slots), "Slots enabled for PUSCH") + ("gnb.stack.mcs", bpo::value(&gnb_stack.mcs)->default_value(gnb_stack.mcs), "PDSCH/PUSCH scheduling modulation code scheme") + ("gnb.stack.log_level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") + ; + + options_gnb_phy.add_options() + ("gnb.phy.nof_threads", bpo::value(&gnb_phy.nof_phy_threads)->default_value(1), "Number of threads") + ("gnb.phy.log.level", bpo::value(&gnb_phy.log.phy_level)->default_value("warning"), "gNb PHY log level") + ("gnb.phy.log.hex_limit", bpo::value(&gnb_phy.log.phy_hex_limit)->default_value(0), "gNb PHY log hex limit") + ("gnb.phy.log.id_preamble", bpo::value(&gnb_phy.log.id_preamble)->default_value("GNB/"), "gNb PHY log ID preamble") + ("gnb.phy.pusch.max_iter", bpo::value(&gnb_phy.pusch_max_nof_iter)->default_value(10), "PUSCH LDPC max number of iterations") + ; + + options_ue_phy.add_options() + ("ue.phy.nof_threads", bpo::value(&ue_phy.nof_phy_threads)->default_value(1), "Number of threads") + ("ue.phy.log.level", bpo::value(&ue_phy.log.phy_level)->default_value("warning"), "UE PHY log level") + ("ue.phy.log.hex_limit", bpo::value(&ue_phy.log.phy_hex_limit)->default_value(0), "UE PHY log hex limit") + ("ue.phy.log.id_preamble", bpo::value(&ue_phy.log.id_preamble)->default_value(" UE/"), "UE PHY log ID preamble") + ; + + options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options() + ("help", "Show this message") + ; + // clang-format on + + bpo::variables_map vm; + try { + bpo::store(bpo::command_line_parser(argc, argv).options(options).run(), vm); + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << e.what() << std::endl; + return; + } + + // help option was given or error - print usage and exit + if (vm.count("help")) { + std::cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << std::endl << std::endl; + std::cout << options << std::endl << std::endl; + return; + } // Load default reference configuration srsran::phy_cfg_nr_default_t::reference_cfg_t reference_cfg; @@ -30,6 +96,22 @@ test_bench::args_t::args_t(int argc, char** argv) cell_list[0].rf_port = 0; cell_list[0].cell_id = 0; cell_list[0].pdcch = phy_cfg.pdcch; + + ue_stack.rnti = rnti; + + gnb_stack.rnti = rnti; + gnb_stack.phy_cfg = phy_cfg; + + if (gnb_stack.dl_length_rb == 0) { + gnb_stack.dl_length_rb = phy_cfg.carrier.nof_prb; + } + + if (gnb_stack.ul_length_rb == 0) { + gnb_stack.ul_length_rb = phy_cfg.carrier.nof_prb; + } + + // Flag configuration as valid + valid = true; } int main(int argc, char** argv) @@ -38,48 +120,19 @@ int main(int argc, char** argv) // Parse test bench arguments test_bench::args_t args(argc, argv); - args.gnb_args.log_id_preamble = "GNB/"; - args.gnb_args.log_level = "info"; - args.gnb_args.nof_phy_threads = 1; - args.ue_args.log.id_preamble = " UE/"; - args.ue_args.log.phy_level = "info"; - args.ue_args.log.phy_hex_limit = 1; - args.ue_args.nof_phy_threads = 1; // Parse arguments TESTASSERT(args.valid); - // Create UE stack arguments - ue_dummy_stack::args_t ue_stack_args = {}; - ue_stack_args.rnti = 0x1234; - - // Create UE stack - ue_dummy_stack ue_stack(ue_stack_args); - TESTASSERT(ue_stack.is_valid()); - - // Create GNB stack arguments - gnb_dummy_stack::args_t gnb_stack_args = {}; - gnb_stack_args.rnti = 0x1234; - gnb_stack_args.mcs = 10; - gnb_stack_args.phy_cfg = args.phy_cfg; - gnb_stack_args.dl_start_rb = 0; - gnb_stack_args.dl_length_rb = args.phy_cfg.carrier.nof_prb; - gnb_stack_args.ul_start_rb = 0; - gnb_stack_args.ul_length_rb = args.phy_cfg.carrier.nof_prb; - - // Create GNB stack - gnb_dummy_stack gnb_stack(gnb_stack_args); - TESTASSERT(gnb_stack.is_valid()); - // Create test bench - test_bench tb(args, gnb_stack, ue_stack); + test_bench tb(args); // Assert bench is initialised correctly TESTASSERT(tb.is_initialised()); // Run per TTI basis - for (uint32_t i = 0; i < 1000; i++) { - TESTASSERT(tb.run_tti()); + while (tb.run_tti()) { + ; // Do nothing } // Stop test bench @@ -89,7 +142,7 @@ int main(int argc, char** argv) srslog::flush(); // Retrieve MAC metrics - srsenb::mac_ue_metrics_t mac_metrics = gnb_stack.get_metrics(); + srsenb::mac_ue_metrics_t mac_metrics = tb.get_gnb_metrics(); // Print metrics float pdsch_bler = 0.0f; diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 91282ed4c..499c66f13 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -22,9 +22,13 @@ class test_bench private: const std::string UE_PHY_COM_LOG_NAME = "UE /PHY/COM"; const std::string GNB_PHY_COM_LOG_NAME = "GNB/PHY/COM"; - uint32_t tti = 0; + uint32_t slot_idx = 0; + uint64_t slot_count = 0; + uint64_t duration_slots; + gnb_dummy_stack gnb_stack; srsenb::nr::worker_pool gnb_phy; phy_common gnb_phy_com; + ue_dummy_stack ue_stack; srsue::nr::worker_pool ue_phy; phy_common ue_phy_com; bool initialised = false; @@ -38,32 +42,38 @@ public: bool valid = false; srsran::phy_cfg_nr_t phy_cfg = {}; srsenb::phy_cell_cfg_list_nr_t cell_list = {}; - srsenb::nr::worker_pool::args_t gnb_args; - srsue::phy_args_nr_t ue_args; - uint16_t rnti = 0x1234; + srsenb::nr::worker_pool::args_t gnb_phy; + gnb_dummy_stack::args_t gnb_stack; + srsue::phy_args_nr_t ue_phy; + ue_dummy_stack::args_t ue_stack; std::string phy_com_log_level = "info"; + uint64_t durations_slots = 100; args_t(int argc, char** argv); }; - test_bench(const args_t& args, srsenb::stack_interface_phy_nr& gnb_stack, srsue::stack_interface_phy_nr& ue_stack) : - ue_phy(args.ue_args.nof_phy_threads), - gnb_phy(gnb_phy_com, gnb_stack, srslog::get_default_sink(), args.gnb_args.nof_phy_threads), + test_bench(const args_t& args) : + gnb_stack(args.gnb_stack), + gnb_phy(gnb_phy_com, gnb_stack, srslog::get_default_sink(), args.gnb_phy.nof_phy_threads), + ue_stack(args.ue_stack), + ue_phy(args.ue_phy.nof_phy_threads), + ue_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)), gnb_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)), - sf_sz((uint32_t)std::round(args.srate_hz * 1e-3)) + sf_sz((uint32_t)std::round(args.srate_hz * 1e-3)), + duration_slots(args.durations_slots) { srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level)); - if (not gnb_phy.init(args.gnb_args, args.cell_list)) { + if (not gnb_phy.init(args.gnb_phy, args.cell_list)) { return; } // Initialise UE PHY - if (not ue_phy.init(args.ue_args, ue_phy_com, &ue_stack, 31)) { + if (not ue_phy.init(args.ue_phy, ue_phy_com, &ue_stack, 31)) { return; } @@ -85,12 +95,12 @@ public: ~test_bench() = default; - bool is_initialised() const { return initialised; } + bool is_initialised() const { return ue_stack.is_valid() and gnb_stack.is_valid() and initialised; } bool run_tti() { // Get gNb worker - srsenb::nr::slot_worker* gnb_worker = gnb_phy.wait_worker(tti); + srsenb::nr::slot_worker* gnb_worker = gnb_phy.wait_worker(slot_idx); if (gnb_worker == nullptr) { return false; } @@ -103,14 +113,14 @@ public: // Set gNb time gnb_time.add(TX_ENB_DELAY * 1e-3); - gnb_worker->set_time(tti, gnb_time); + gnb_worker->set_time(slot_idx, gnb_time); // Start gNb work gnb_phy_com.push_semaphore(gnb_worker); gnb_phy.start_worker(gnb_worker); // Get UE worker - srsue::nr::sf_worker* ue_worker = ue_phy.wait_worker(tti); + srsue::nr::sf_worker* ue_worker = ue_phy.wait_worker(slot_idx); if (ue_worker == nullptr) { return false; } @@ -123,16 +133,19 @@ public: // Set UE time ue_time.add(TX_ENB_DELAY * 1e-3); - ue_worker->set_tti(tti); + ue_worker->set_tti(slot_idx); ue_worker->set_tx_time(ue_time); // Start gNb work ue_phy_com.push_semaphore(ue_worker); ue_phy.start_worker(ue_worker); - tti++; - return true; + slot_count++; + slot_idx = slot_count % (1024 * SRSRAN_NSLOTS_PER_FRAME_NR(srsran_subcarrier_spacing_15kHz)); + return slot_count <= duration_slots; } + + srsenb::mac_ue_metrics_t get_gnb_metrics() { return gnb_stack.get_metrics(); } }; #endif // SRSRAN_TEST_BENCH_H From d12085e8a7f3c6cbf3e1d9c41b2b8167b4dcea53 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 6 Jul 2021 18:30:47 +0200 Subject: [PATCH 03/59] Added different NR PHY test cases --- test/phy/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 0e4f0f627..40939260c 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -21,7 +21,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) - add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pusch.slots="") - add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots="") - add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test --duration=100) + add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" --gnb.stack.pusch.slots=\"\") + add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"\" --gnb.stack.pusch.slots=\"6,7,8,9\") + add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" --gnb.stack.pusch.slots=\"6,7,8,9\") endif () From 248a52b33d1024ece3b454e2bf1b4a46fbe01896 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 10:24:34 +0200 Subject: [PATCH 04/59] Enhanced NR PHY test --- test/phy/dummy_gnb_stack.h | 87 +++++++++++++++++++------------------- test/phy/nr_phy_test.cc | 27 +++++++----- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 880625342..1941beff4 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -27,20 +27,19 @@ class gnb_dummy_stack : public srsenb::stack_interface_phy_nr { private: - srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); - const uint16_t rnti = 0x1234; - const uint32_t mcs = 1; - srsran::circular_array dci_dl_location; - srsran::circular_array dci_ul_location; - srsran::circular_array dl_data_to_ul_ack; - uint32_t ss_id = 0; - uint32_t dl_freq_res = 0; - uint32_t ul_freq_res = 0; - srsran_random_t random_gen = nullptr; - srsran::phy_cfg_nr_t phy_cfg = {}; - bool valid = false; - std::set dl_slots; - std::set ul_slots; + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); + const uint16_t rnti = 0x1234; + struct { + srsran::circular_array dci_location; + uint32_t mcs; + uint32_t freq_res = 0; + std::set slots; + } dl, ul; + srsran::circular_array dl_data_to_ul_ack; + uint32_t ss_id = 0; + srsran_random_t random_gen = nullptr; + srsran::phy_cfg_nr_t phy_cfg = {}; + bool valid = false; std::mutex mac_metrics_mutex; srsenb::mac_ue_metrics_t mac_metrics = {}; @@ -120,7 +119,7 @@ private: bool schedule_pdsch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - if (dl_slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx)) == 0) { + if (dl.slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx)) == 0) { return true; } @@ -135,7 +134,7 @@ private: pdcch.dci_cfg = phy_cfg.get_dci_cfg(); // Fill DCI context - if (not phy_cfg.get_dci_ctx_pdsch_rnti_c(ss_id, dci_dl_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { + if (not phy_cfg.get_dci_ctx_pdsch_rnti_c(ss_id, dl.dci_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { logger.error("Error filling PDSCH DCI context"); return false; } @@ -145,9 +144,9 @@ private: // Fill DCI fields srsran_dci_dl_nr_t& dci = pdcch.dci; - dci.freq_domain_assigment = dl_freq_res; + dci.freq_domain_assigment = dl.freq_res; dci.time_domain_assigment = 0; - dci.mcs = mcs; + dci.mcs = dl.mcs; dci.rv = 0; dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; @@ -198,7 +197,7 @@ private: bool schedule_pusch(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - if (ul_slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx + 4)) == 0) { + if (ul.slots.count(SRSRAN_SLOT_NR_MOD(srsran_subcarrier_spacing_15kHz, slot_cfg.idx + 4)) == 0) { return true; } @@ -209,17 +208,17 @@ private: pdcch.dci_cfg = phy_cfg.get_dci_cfg(); // Fill DCI context - if (not phy_cfg.get_dci_ctx_pusch_rnti_c(ss_id, dci_ul_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { + if (not phy_cfg.get_dci_ctx_pusch_rnti_c(ss_id, ul.dci_location[slot_cfg.idx], rnti, pdcch.dci.ctx)) { logger.error("Error filling PDSCH DCI context"); return false; } // Fill DCI fields srsran_dci_ul_nr_t& dci = pdcch.dci; - dci.freq_domain_assigment = ul_freq_res; + dci.freq_domain_assigment = ul.freq_res; dci.time_domain_assigment = 0; dci.freq_hopping_flag = 0; - dci.mcs = mcs; + dci.mcs = ul.mcs; dci.rv = 0; dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2; dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME; @@ -265,29 +264,31 @@ private: public: struct args_t { - srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration - uint16_t rnti = 0x1234; ///< C-RNTI - uint32_t mcs = 10; ///< Modulation code scheme - uint32_t ss_id = 1; ///< Search Space identifier - uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level - uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index - uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index - uint32_t dl_start_rb = 0; ///< Start resource block - uint32_t dl_length_rb = 0; ///< Number of resource blocks - std::string dl_sched_slots = "0,1,2,3,4,5"; ///< PDCH Slot list - uint32_t ul_start_rb = 0; ///< Start resource block - uint32_t ul_length_rb = 0; ///< Number of resource blocks - std::string ul_sched_slots = "6,7,8,9"; ///< Slot list - std::string log_level = "warning"; + srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + uint16_t rnti = 0x1234; ///< C-RNTI + uint32_t ss_id = 1; ///< Search Space identifier + uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level + uint32_t pdcch_dl_candidate = 0; ///< PDCCH DL DCI candidate index + uint32_t pdcch_ul_candidate = 1; ///< PDCCH UL DCI candidate index + struct { + uint32_t rb_start = 0; ///< Start frequency domain resource block + uint32_t rb_length = 10; ///< Number of frequency domain resource blocks + uint32_t mcs = 10; ///< Modulation code scheme + std::string slots = ""; ///< Slot list, empty string means no scheduling + } pdsch, pusch; + std::string log_level = "warning"; }; - gnb_dummy_stack(const args_t& args) : mcs(args.mcs), rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) + gnb_dummy_stack(const args_t& args) : rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) { random_gen = srsran_random_init(0x1234); logger.set_level(srslog::str_to_basic_level(args.log_level)); - srsran::string_parse_list(args.dl_sched_slots, ',', dl_slots); - srsran::string_parse_list(args.ul_sched_slots, ',', ul_slots); + dl.mcs = args.pdsch.mcs; + ul.mcs = args.pusch.mcs; + + srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + srsran::string_parse_list(args.pusch.slots, ',', ul.slots); // Select DCI locations for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) { @@ -307,7 +308,7 @@ public: args.pdcch_aggregation_level); return; } - dci_dl_location[slot] = locations[args.pdcch_dl_candidate]; + dl.dci_location[slot] = locations[args.pdcch_dl_candidate]; // DCI UL if (args.pdcch_ul_candidate >= locations.size()) { @@ -317,14 +318,14 @@ public: args.pdcch_aggregation_level); return; } - dci_ul_location[slot] = locations[args.pdcch_ul_candidate]; + ul.dci_location[slot] = locations[args.pdcch_ul_candidate]; } // Select DL frequency domain resources - dl_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.dl_start_rb, args.dl_length_rb); + dl.freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.pdsch.rb_start, args.pdsch.rb_length); // Select DL frequency domain resources - ul_freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.ul_start_rb, args.ul_length_rb); + ul.freq_res = srsran_ra_nr_type1_riv(args.phy_cfg.carrier.nof_prb, args.pusch.rb_start, args.pusch.rb_length); // Setup DL Data to ACK timing for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index df570516f..3c7feb61f 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -31,6 +31,9 @@ test_bench::args_t::args_t(int argc, char** argv) uint16_t rnti = 0x1234; + gnb_stack.pdsch.slots = "0,1,2,3,4,5"; + gnb_stack.pusch.slots = "6,7,8,9"; + // clang-format off options.add_options() ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") @@ -40,14 +43,14 @@ test_bench::args_t::args_t(int argc, char** argv) options_gnb_stack.add_options() ("gnb.stack.pdcch.aggregation_level", bpo::value(&gnb_stack.pdcch_aggregation_level)->default_value(gnb_stack.pdcch_aggregation_level), "PDCCH aggregation level") ("gnb.stack.pdsch.candidate", bpo::value(&gnb_stack.pdcch_dl_candidate)->default_value(gnb_stack.pdcch_dl_candidate), "PDCCH candidate index for PDSCH") - ("gnb.stack.pdsch.start", bpo::value(&gnb_stack.dl_start_rb)->default_value(0), "PDSCH scheduling frequency allocation start") - ("gnb.stack.pdsch.length", bpo::value(&gnb_stack.dl_length_rb)->default_value(gnb_stack.dl_length_rb), "PDSCH scheduling frequency allocation length") - ("gnb.stack.pdsch.slots", bpo::value(&gnb_stack.dl_sched_slots)->default_value(gnb_stack.dl_sched_slots), "Slots enabled for PDSCH") + ("gnb.stack.pdsch.start", bpo::value(&gnb_stack.pdsch.rb_start)->default_value(0), "PDSCH scheduling frequency allocation start") + ("gnb.stack.pdsch.length", bpo::value(&gnb_stack.pdsch.rb_length)->default_value(gnb_stack.pdsch.rb_length), "PDSCH scheduling frequency allocation length") + ("gnb.stack.pdsch.slots", bpo::value(&gnb_stack.pdsch.slots)->default_value(gnb_stack.pdsch.slots), "Slots enabled for PDSCH") + ("gnb.stack.pdsch.mcs", bpo::value(&gnb_stack.pdsch.mcs)->default_value(gnb_stack.pdsch.mcs), "PDSCH/PUSCH scheduling modulation code scheme") ("gnb.stack.pusch.candidate", bpo::value(&gnb_stack.pdcch_ul_candidate)->default_value(gnb_stack.pdcch_ul_candidate), "PDCCH candidate index for PUSCH") - ("gnb.stack.pusch.start", bpo::value(&gnb_stack.ul_start_rb)->default_value(0), "PUSCH scheduling frequency allocation start") - ("gnb.stack.pusch.length", bpo::value(&gnb_stack.ul_length_rb)->default_value(gnb_stack.ul_length_rb), "PUSCH scheduling frequency allocation length") - ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.ul_sched_slots)->default_value(gnb_stack.ul_sched_slots), "Slots enabled for PUSCH") - ("gnb.stack.mcs", bpo::value(&gnb_stack.mcs)->default_value(gnb_stack.mcs), "PDSCH/PUSCH scheduling modulation code scheme") + ("gnb.stack.pusch.start", bpo::value(&gnb_stack.pusch.rb_start)->default_value(0), "PUSCH scheduling frequency allocation start") + ("gnb.stack.pusch.length", bpo::value(&gnb_stack.pusch.rb_length)->default_value(gnb_stack.pusch.rb_length), "PUSCH scheduling frequency allocation length") + ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.pusch.slots)->default_value(gnb_stack.pusch.slots), "Slots enabled for PUSCH") ("gnb.stack.log_level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") ; @@ -102,12 +105,14 @@ test_bench::args_t::args_t(int argc, char** argv) gnb_stack.rnti = rnti; gnb_stack.phy_cfg = phy_cfg; - if (gnb_stack.dl_length_rb == 0) { - gnb_stack.dl_length_rb = phy_cfg.carrier.nof_prb; + if (gnb_stack.pdsch.rb_length == 0) { + gnb_stack.pdsch.rb_length = phy_cfg.carrier.nof_prb; + gnb_stack.pdsch.rb_start = 0; } - if (gnb_stack.ul_length_rb == 0) { - gnb_stack.ul_length_rb = phy_cfg.carrier.nof_prb; + if (gnb_stack.pusch.rb_length == 0) { + gnb_stack.pusch.rb_length = phy_cfg.carrier.nof_prb; + gnb_stack.pdsch.rb_start = 0; } // Flag configuration as valid From 35840d6bc13fde39c09ccfe57ebfdbe54ff19882 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 12:47:30 +0200 Subject: [PATCH 05/59] Removed all zero condition from LDPC decoding --- lib/src/phy/phch/sch_nr.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index b8a5390ba..57f4ff84f 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -646,19 +646,10 @@ static int sch_nr_decode(srsran_sch_nr_t* q, nof_iter_sum += n_iter_cb; // Check if CB is all zeros - uint32_t cb_len = cfg.Kp - cfg.L_cb; - bool all_zeros = true; - for (uint32_t i = 0; i < cb_len && all_zeros; i++) { - all_zeros = (q->temp_cb[i] == 0); - } + uint32_t cb_len = cfg.Kp - cfg.L_cb; - tb->softbuffer.rx->cb_crc[r] = (ret != 0) && (!all_zeros); - SCH_INFO_RX("CB %d/%d iter=%d CRC=%s all_zeros=%s", - r, - cfg.C, - n_iter_cb, - tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO", - all_zeros ? "yes" : "no"); + tb->softbuffer.rx->cb_crc[r] = (ret != 0); + SCH_INFO_RX("CB %d/%d iter=%d CRC=%s", r, cfg.C, n_iter_cb, tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO"); // CB Debug trace if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { From 11a52248cdb485f65548221dc110af9defa435a4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 14:12:55 +0200 Subject: [PATCH 06/59] RA NR Calculates actual PUSCH rate --- lib/src/phy/phch/ra_nr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index fd58a698a..e252e2f43 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -1040,6 +1040,12 @@ int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier, for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { pusch_cfg->grant.tb[i].nof_bits = pusch_cfg->grant.tb[i].nof_re * srsran_mod_bits_x_symbol(pusch_cfg->grant.tb[i].mod) - Gack - Gcsi1 - Gcsi2; + + if (pusch_cfg->grant.tb[i].nof_bits > 0) { + pusch_cfg->grant.tb[i].R_prime = (double)pusch_cfg->grant.tb[i].tbs / (double)pusch_cfg->grant.tb[i].nof_bits; + } else { + pusch_cfg->grant.tb[i].R_prime = NAN; + } } return SRSRAN_SUCCESS; From ef865b81a3d5436273c8b1abf7956e744ccad46b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 14:13:29 +0200 Subject: [PATCH 07/59] NR SCH TB information prints actual rate and not the target rate --- lib/src/phy/phch/sch_nr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index 57f4ff84f..6f7bb435a 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -771,7 +771,7 @@ int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, const srsran_sch_tb_res_nr_ tb->cw_idx, srsran_mod_string(tb->mod), tb->tbs / 8, - tb->R, + tb->R_prime, tb->rv); if (res != NULL) { From 04aca98e5fe69d00b73781ef349ccbfdd918cf40 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 14:14:03 +0200 Subject: [PATCH 08/59] Added more checks in PUSCH NR test --- lib/src/phy/phch/test/pusch_nr_test.c | 48 ++++++++++++++++++--------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 508649ab7..8ec72d619 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -277,25 +277,43 @@ int main(int argc, char** argv) goto clean_exit; } - float mse = 0.0f; + // Check symbols Mean Square Error (MSE) uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_cfg.grant); - for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) { - for (uint32_t j = 0; j < nof_re; j++) { - mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]); - } - } if (nof_re * pusch_cfg.grant.nof_layers > 0) { - mse = mse / (nof_re * pusch_cfg.grant.nof_layers); - } - if (mse > 0.001) { - ERROR("MSE error (%f) is too high", mse); + float mse = 0.0f; for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) { - printf("d_tx[%d]=", i); - srsran_vec_fprint_c(stdout, pusch_tx.d[i], nof_re); - printf("d_rx[%d]=", i); - srsran_vec_fprint_c(stdout, pusch_rx.d[i], nof_re); + for (uint32_t j = 0; j < nof_re; j++) { + mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]); + } + } + mse = mse / (nof_re * pusch_cfg.grant.nof_layers); + if (mse > 0.001) { + ERROR("MSE error (%f) is too high", mse); + for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) { + printf("d_tx[%d]=", i); + srsran_vec_fprint_c(stdout, pusch_tx.d[i], nof_re); + printf("d_rx[%d]=", i); + srsran_vec_fprint_c(stdout, pusch_rx.d[i], nof_re); + } + goto clean_exit; + } + } + + // Check Received SCH LLR match + if (pusch_rx.G_ulsch > 0) { + for (uint32_t i = 0; i < pusch_rx.G_ulsch; i++) { + uint8_t rx_bit = (((int8_t*)pusch_rx.g_ulsch)[i]) < 0 ? 1 : 0; + pusch_rx.g_ulsch[i] = rx_bit; + } + if (memcmp(pusch_tx.g_ulsch, pusch_rx.g_ulsch, pusch_tx.G_ulsch) != 0) { + printf("g_ulsch_tx="); + srsran_vec_fprint_byte(stdout, pusch_tx.g_ulsch, pusch_tx.G_ulsch); + printf("g_ulsch_rx="); + srsran_vec_fprint_byte(stdout, pusch_rx.g_ulsch, pusch_tx.G_ulsch); + // srsran_vec_fprint_bs(stdout, (int8_t*)pusch_rx.g_ulsch, pusch_rx.G_ulsch); + + goto clean_exit; } - goto clean_exit; } // Validate UL-SCH CRC check From f5a3fcf2b6c0fe6cb94dc3684d0df2d9a37d1b34 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 14:15:35 +0200 Subject: [PATCH 09/59] More NR PHY test enhacements --- test/phy/CMakeLists.txt | 21 +++++++++++++++++++-- test/phy/nr_phy_test.cc | 22 ++++++++++++---------- test/phy/test_bench.h | 11 +++++++++++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 40939260c..ba74f1f18 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -22,6 +22,23 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${ATOMIC_LIBS}) add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" --gnb.stack.pusch.slots=\"\") - add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"\" --gnb.stack.pusch.slots=\"6,7,8,9\") - add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" --gnb.stack.pusch.slots=\"6,7,8,9\") + add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test + --duration=100 # 100 slots + --gnb.stack.pdsch.slots=6 # No PDSCH + --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pusch.start=0 # Start at RB 0 + --gnb.stack.pusch.length=52 # Full 10 MHz BW + --gnb.stack.pusch.mcs=28 # Maximum MCS + ) + add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test + --duration=100 # 100 slots + --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.start=0 # Start at RB 0 + --gnb.stack.pdsch.length=52 # Full 10 MHz BW + --gnb.stack.pdsch.mcs=28 # Maximum MCS + --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pusch.start=0 # Start at RB 0 + --gnb.stack.pusch.length=52 # Full 10 MHz BW + --gnb.stack.pusch.mcs=28 # Maximum MCS + ) endif () diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 3c7feb61f..8b78cf03a 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -36,22 +36,24 @@ test_bench::args_t::args_t(int argc, char** argv) // clang-format off options.add_options() - ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") - ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") + ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") + ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") + ("lib.log.level", bpo::value(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level") ; options_gnb_stack.add_options() ("gnb.stack.pdcch.aggregation_level", bpo::value(&gnb_stack.pdcch_aggregation_level)->default_value(gnb_stack.pdcch_aggregation_level), "PDCCH aggregation level") ("gnb.stack.pdsch.candidate", bpo::value(&gnb_stack.pdcch_dl_candidate)->default_value(gnb_stack.pdcch_dl_candidate), "PDCCH candidate index for PDSCH") - ("gnb.stack.pdsch.start", bpo::value(&gnb_stack.pdsch.rb_start)->default_value(0), "PDSCH scheduling frequency allocation start") - ("gnb.stack.pdsch.length", bpo::value(&gnb_stack.pdsch.rb_length)->default_value(gnb_stack.pdsch.rb_length), "PDSCH scheduling frequency allocation length") - ("gnb.stack.pdsch.slots", bpo::value(&gnb_stack.pdsch.slots)->default_value(gnb_stack.pdsch.slots), "Slots enabled for PDSCH") - ("gnb.stack.pdsch.mcs", bpo::value(&gnb_stack.pdsch.mcs)->default_value(gnb_stack.pdsch.mcs), "PDSCH/PUSCH scheduling modulation code scheme") + ("gnb.stack.pdsch.start", bpo::value(&gnb_stack.pdsch.rb_start)->default_value(0), "PDSCH scheduling frequency allocation start") + ("gnb.stack.pdsch.length", bpo::value(&gnb_stack.pdsch.rb_length)->default_value(gnb_stack.pdsch.rb_length), "PDSCH scheduling frequency allocation length") + ("gnb.stack.pdsch.slots", bpo::value(&gnb_stack.pdsch.slots)->default_value(gnb_stack.pdsch.slots), "Slots enabled for PDSCH") + ("gnb.stack.pdsch.mcs", bpo::value(&gnb_stack.pdsch.mcs)->default_value(gnb_stack.pdsch.mcs), "PDSCH scheduling modulation code scheme") ("gnb.stack.pusch.candidate", bpo::value(&gnb_stack.pdcch_ul_candidate)->default_value(gnb_stack.pdcch_ul_candidate), "PDCCH candidate index for PUSCH") - ("gnb.stack.pusch.start", bpo::value(&gnb_stack.pusch.rb_start)->default_value(0), "PUSCH scheduling frequency allocation start") - ("gnb.stack.pusch.length", bpo::value(&gnb_stack.pusch.rb_length)->default_value(gnb_stack.pusch.rb_length), "PUSCH scheduling frequency allocation length") - ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.pusch.slots)->default_value(gnb_stack.pusch.slots), "Slots enabled for PUSCH") - ("gnb.stack.log_level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") + ("gnb.stack.pusch.start", bpo::value(&gnb_stack.pusch.rb_start)->default_value(0), "PUSCH scheduling frequency allocation start") + ("gnb.stack.pusch.length", bpo::value(&gnb_stack.pusch.rb_length)->default_value(gnb_stack.pusch.rb_length), "PUSCH scheduling frequency allocation length") + ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.pusch.slots)->default_value(gnb_stack.pusch.slots), "Slots enabled for PUSCH") + ("gnb.stack.pusch.mcs", bpo::value(&gnb_stack.pusch.mcs)->default_value(gnb_stack.pusch.mcs), "PUSCH scheduling modulation code scheme") + ("gnb.stack.log.level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") ; options_gnb_phy.add_options() diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 499c66f13..aa296dbe0 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -47,6 +47,7 @@ public: srsue::phy_args_nr_t ue_phy; ue_dummy_stack::args_t ue_stack; std::string phy_com_log_level = "info"; + std::string phy_lib_log_level = "none"; uint64_t durations_slots = 100; args_t(int argc, char** argv); @@ -82,6 +83,16 @@ public: return; } + // Make sure PHY log is not set by UE or gNb PHY + handler_registered = 0; + if (args.phy_lib_log_level == "info") { + srsran_verbose = SRSRAN_VERBOSE_INFO; + } else if (args.phy_lib_log_level == "debug") { + srsran_verbose = SRSRAN_VERBOSE_DEBUG; + } else { + srsran_verbose = SRSRAN_VERBOSE_NONE; + } + initialised = true; } From 3416aad16d048ecc7bd2659865191676de42dea2 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 16:01:34 +0200 Subject: [PATCH 10/59] Fix PUSCH NR test false alarm --- lib/src/phy/phch/test/pusch_nr_test.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 8ec72d619..fbffeefaa 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -303,7 +303,11 @@ int main(int argc, char** argv) if (pusch_rx.G_ulsch > 0) { for (uint32_t i = 0; i < pusch_rx.G_ulsch; i++) { uint8_t rx_bit = (((int8_t*)pusch_rx.g_ulsch)[i]) < 0 ? 1 : 0; - pusch_rx.g_ulsch[i] = rx_bit; + if (rx_bit == 0) { + pusch_rx.g_ulsch[i] = pusch_tx.g_ulsch[i]; + } else { + pusch_rx.g_ulsch[i] = rx_bit; + } } if (memcmp(pusch_tx.g_ulsch, pusch_rx.g_ulsch, pusch_tx.G_ulsch) != 0) { printf("g_ulsch_tx="); From 603c67e36ddaab30da23c79d9a8d7f0646fed723 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 16:03:04 +0200 Subject: [PATCH 11/59] Set g_ulsch LLR overlaped with g_harq_ack to zero --- lib/src/phy/phch/pusch_nr.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 184ac6f62..385059df2 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -839,6 +839,13 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, // Demultiplex UCI only if necessary if (q->uci_mux) { + // As it can be HARQ-ACK takes LLRs from ULSCH, demultiplex HARQ-ACK first + int8_t* g_ack = (int8_t*)q->g_ack; + for (uint32_t i = 0; i < q->G_ack; i++) { + g_ack[i] = llr[q->pos_ack[i]]; + llr[q->pos_ack[i]] = 0; + } + // Demultiplex UL-SCH, change sign int8_t* g_ulsch = (int8_t*)q->g_ulsch; for (uint32_t i = 0; i < q->G_ulsch; i++) { @@ -848,12 +855,6 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, g_ulsch[i] = 0; } - // Demultiplex HARQ-ACK - int8_t* g_ack = (int8_t*)q->g_ack; - for (uint32_t i = 0; i < q->G_ack; i++) { - g_ack[i] = llr[q->pos_ack[i]]; - } - // Demultiplex CSI part 1 int8_t* g_csi1 = (int8_t*)q->g_csi1; for (uint32_t i = 0; i < q->G_csi1; i++) { From 54a12870ec34020b293d67e4e46477f2ca0678ff Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 16:59:56 +0200 Subject: [PATCH 12/59] SRSUE: avoid negative SR transmission in NR --- lib/include/srsran/phy/phch/uci_cfg_nr.h | 12 ++++++------ lib/src/phy/phch/ra_ul_nr.c | 2 +- lib/src/phy/phch/uci_nr.c | 11 ++++++++++- srsue/hdr/phy/nr/state.h | 10 +++++----- srsue/src/phy/nr/cc_worker.cc | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/include/srsran/phy/phch/uci_cfg_nr.h b/lib/include/srsran/phy/phch/uci_cfg_nr.h index cb1e104ca..ca5b63274 100644 --- a/lib/include/srsran/phy/phch/uci_cfg_nr.h +++ b/lib/include/srsran/phy/phch/uci_cfg_nr.h @@ -35,12 +35,11 @@ * @brief Uplink Control Information bits configuration for PUCCH transmission */ typedef struct { - uint16_t rnti; ///< RNTI - uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1 - uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception - uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1 - uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR - bool sr_positive_present; ///< Set to true if there is at least one positive SR + uint16_t rnti; ///< RNTI + uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1 + uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception + uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1 + uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR } srsran_uci_nr_pucch_cfg_t; /** @@ -70,6 +69,7 @@ typedef struct SRSRAN_API { /// Common Parameters srsran_harq_ack_cfg_t ack; ///< HARQ-ACK configuration uint32_t o_sr; ///< Number of SR bits + bool sr_positive_present; ///< Set to true if there is at least one positive SR srsran_csi_report_cfg_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< CSI report configuration uint32_t nof_csi; ///< Number of CSI reports union { diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index ce4e722bd..1f6a03332 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -530,7 +530,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // - At least one positive SR // - up to 2 HARQ-ACK // - No CSI report - if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && + if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && uci_cfg->nof_csi == 0) { uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index 14e169441..88412ac5a 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -980,7 +980,16 @@ uint32_t srsran_uci_nr_total_bits(const srsran_uci_cfg_nr_t* uci_cfg) return 0; } - return uci_cfg->ack.count + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); + uint32_t o_csi = srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); + + // According to 38.213 9.2.4 UE procedure for reporting SR + // The UE transmits a PUCCH in the PUCCH resource for the corresponding SR configuration only when the UE transmits a + // positive SR + if (uci_cfg->ack.count == 0 && o_csi == 0 && !uci_cfg->sr_positive_present) { + return 0; + } + + return uci_cfg->ack.count + uci_cfg->o_sr + o_csi; } uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uint32_t str_len) diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index fef7d2986..fed29376a 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -316,7 +316,7 @@ public: } // Initialise counters - uint32_t sr_count_all = (uint32_t)n; + uint32_t sr_count_all = (uint32_t)n; // Number of opportunities in this TTI uint32_t sr_count_positive = 0; // Iterate all opportunities and check if there is a pending SR @@ -333,10 +333,10 @@ public: } // Configure SR fields in UCI data - uci_data.cfg.pucch.sr_resource_id = sr_resource_id[0]; - uci_data.cfg.o_sr = srsran_ra_ul_nr_nof_sr_bits(sr_count_all); - uci_data.cfg.pucch.sr_positive_present = sr_count_positive > 0; - uci_data.value.sr = sr_count_positive; + uci_data.cfg.pucch.sr_resource_id = sr_resource_id[0]; + uci_data.cfg.o_sr = srsran_ra_ul_nr_nof_sr_bits(sr_count_all); + uci_data.cfg.sr_positive_present = sr_count_positive > 0; + uci_data.value.sr = sr_count_positive; } void get_periodic_csi(const uint32_t& tti, srsran_uci_data_nr_t& uci_data) diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index e9c4cbde2..6f69a5e2b 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -538,7 +538,7 @@ bool cc_worker::work_ul() } // Add SR to UCI data only if there is no UL grant! - if (!has_ul_ack) { + if (not has_pusch_grant) { phy.get_pending_sr(ul_slot_cfg.idx, uci_data); } From b82491bc746124f8bb55bee68b75d1be03620b6a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 18:00:01 +0200 Subject: [PATCH 13/59] Added SR option in NR PHY Test --- test/phy/dummy_ue_stack.h | 20 +++++++++++++++++--- test/phy/nr_phy_test.cc | 4 ++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index 0a3c51a3c..939de1e86 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -21,15 +21,18 @@ private: srsran_random_t random_gen = srsran_random_init(0x4567); uint16_t rnti = 0; bool valid = false; + uint32_t sr_period = 0; + uint32_t sr_count = 0; srsran::circular_array tx_harq_proc; srsran::circular_array rx_harq_proc; public: struct args_t { - uint16_t rnti = 0x1234; + uint16_t rnti = 0x1234; ///< C-RNTI for PUSCH and PDSCH transmissions + uint32_t sr_period = 0; ///< Indicates positive SR period in number of opportunities. Set to 0 to disable. }; - ue_dummy_stack(const args_t& args) : rnti(args.rnti) { valid = true; } + ue_dummy_stack(const args_t& args) : rnti(args.rnti), sr_period(args.sr_period) { valid = true; } ~ue_dummy_stack() { srsran_random_free(random_gen); } void in_sync() override {} void out_of_sync() override {} @@ -54,7 +57,18 @@ public: srsran_random_byte_vector(random_gen, action->tb.payload->msg, grant.tbs / 8); } void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} - bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override { return false; } + bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override + { + if (sr_period == 0) { + return false; + } + + bool ret = (sr_count % sr_period == 0); + + sr_count++; + + return ret; + } bool is_valid() const { return valid; } }; diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 8b78cf03a..78cfe3c46 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -71,6 +71,10 @@ test_bench::args_t::args_t(int argc, char** argv) ("ue.phy.log.id_preamble", bpo::value(&ue_phy.log.id_preamble)->default_value(" UE/"), "UE PHY log ID preamble") ; + options_ue_stack.add_options() + ("ue.stack.sr.period", bpo::value(&ue_stack.sr_period)->default_value(ue_stack.sr_period), "SR period in number of opportunities. Set 0 to disable and 1 for all.") + ; + options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options() ("help", "Show this message") ; From 1f3b3d5ef28543358dd1c78c96dcda322d771932 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 18:00:27 +0200 Subject: [PATCH 14/59] Show PDSCH and PUSCH metrics if any transmitted --- test/phy/nr_phy_test.cc | 63 ++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 78cfe3c46..2505a2645 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -155,38 +155,43 @@ int main(int argc, char** argv) // Retrieve MAC metrics srsenb::mac_ue_metrics_t mac_metrics = tb.get_gnb_metrics(); - // Print metrics - float pdsch_bler = 0.0f; - if (mac_metrics.tx_pkts != 0) { - pdsch_bler = (float)mac_metrics.tx_errors / (float)mac_metrics.tx_pkts; - } - float pusch_bler = 0.0f; - if (mac_metrics.rx_pkts != 0) { - pusch_bler = (float)mac_metrics.rx_errors / (float)mac_metrics.rx_pkts; - } - float pdsch_shed_rate = 0.0f; - if (mac_metrics.tx_pkts != 0) { - pdsch_shed_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; - } - float pusch_shed_rate = 0.0f; - if (mac_metrics.rx_pkts != 0) { - pusch_shed_rate = (float)mac_metrics.rx_brate / (float)mac_metrics.rx_pkts / 1000.0f; + // Print PDSCH metrics if scheduled + if (mac_metrics.tx_pkts > 0) { + float pdsch_bler = 0.0f; + pdsch_bler = (float)mac_metrics.tx_errors / (float)mac_metrics.tx_pkts; + + float pdsch_shed_rate = 0.0f; + pdsch_shed_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; + + srsran::console("PDSCH:\n"); + srsran::console(" Count: %d\n", mac_metrics.tx_pkts); + srsran::console(" BLER: %f\n", pdsch_bler); + srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate); + srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate); + srsran::console(" Retx Rate: %f Mbps\n", pdsch_bler * pdsch_shed_rate); + srsran::console("\n"); } - srsran::console("PDSCH:\n"); - srsran::console(" Count: %d\n", mac_metrics.tx_pkts); - srsran::console(" BLER: %f\n", pdsch_bler); - srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate); - srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate); - srsran::console(" Retx Rate: %f Mbps\n", pdsch_bler * pdsch_shed_rate); + // Print PUSCH metrics if scheduled + if (mac_metrics.rx_pkts > 0) { + float pusch_bler = 0.0f; + if (mac_metrics.rx_pkts != 0) { + pusch_bler = (float)mac_metrics.rx_errors / (float)mac_metrics.rx_pkts; + } - srsran::console("\n"); - srsran::console("PUSCH:\n"); - srsran::console(" Count: %d\n", mac_metrics.rx_pkts); - srsran::console(" BLER: %f\n", pusch_bler); - srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate); - srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate); - srsran::console(" Retx Rate: %f Mbps\n", pusch_bler * pusch_shed_rate); + float pusch_shed_rate = 0.0f; + if (mac_metrics.rx_pkts != 0) { + pusch_shed_rate = (float)mac_metrics.rx_brate / (float)mac_metrics.rx_pkts / 1000.0f; + } + + srsran::console("PUSCH:\n"); + srsran::console(" Count: %d\n", mac_metrics.rx_pkts); + srsran::console(" BLER: %f\n", pusch_bler); + srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate); + srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate); + srsran::console(" Retx Rate: %f Mbps\n", pusch_bler * pusch_shed_rate); + srsran::console("\n"); + } // Assert metrics TESTASSERT(mac_metrics.tx_errors == 0); From 5ed241fc9b723e0409d737eaa967b41d325ad941 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 9 Jul 2021 11:52:12 +0200 Subject: [PATCH 15/59] Fix unitialised NR PHY test data --- test/phy/dummy_ue_stack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index 939de1e86..f2633e5c4 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -54,7 +54,7 @@ public: action->tb.enabled = true; action->tb.payload = &tx_harq_proc[grant.pid].get_tb(grant.tbs); action->tb.softbuffer = &tx_harq_proc[grant.pid].get_softbuffer(grant.ndi); - srsran_random_byte_vector(random_gen, action->tb.payload->msg, grant.tbs / 8); + srsran_random_byte_vector(random_gen, action->tb.payload->msg, grant.tbs); } void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) override {} bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx) override From 6c82d63aa68e63cfdb0be0a295fec8cde33ad7c9 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 8 Jul 2021 16:13:09 +0200 Subject: [PATCH 16/59] remove legacy PNF/VNF code the code hasn't been maintained for a while an likely needs to be adapted for a real-world scenarios. in order to avoid having to maintain two MAC/PHY interfaces we remove the code from now. --- lib/include/srsran/common/basic_pnf.h | 549 ---------------------- lib/include/srsran/common/basic_vnf.h | 81 ---- lib/include/srsran/common/basic_vnf_api.h | 159 ------- lib/src/common/CMakeLists.txt | 3 +- lib/src/common/basic_vnf.cc | 399 ---------------- lib/test/common/CMakeLists.txt | 6 - lib/test/common/pnf_bridge.cc | 118 ----- lib/test/common/pnf_dummy.cc | 108 ----- srsenb/hdr/phy/vnf_phy_nr.h | 63 --- srsenb/src/CMakeLists.txt | 2 +- srsenb/src/enb.cc | 38 +- srsenb/src/phy/CMakeLists.txt | 2 - srsenb/src/phy/vnf_phy_nr.cc | 67 --- srsue/hdr/phy/vnf_phy_nr.h | 73 --- srsue/src/phy/CMakeLists.txt | 5 +- srsue/src/phy/vnf_phy_nr.cc | 82 ---- srsue/src/ue.cc | 8 +- test/phy/CMakeLists.txt | 1 - 18 files changed, 10 insertions(+), 1754 deletions(-) delete mode 100644 lib/include/srsran/common/basic_pnf.h delete mode 100644 lib/include/srsran/common/basic_vnf.h delete mode 100644 lib/include/srsran/common/basic_vnf_api.h delete mode 100644 lib/src/common/basic_vnf.cc delete mode 100644 lib/test/common/pnf_bridge.cc delete mode 100644 lib/test/common/pnf_dummy.cc delete mode 100644 srsenb/hdr/phy/vnf_phy_nr.h delete mode 100644 srsenb/src/phy/vnf_phy_nr.cc delete mode 100644 srsue/hdr/phy/vnf_phy_nr.h delete mode 100644 srsue/src/phy/vnf_phy_nr.cc diff --git a/lib/include/srsran/common/basic_pnf.h b/lib/include/srsran/common/basic_pnf.h deleted file mode 100644 index fdd1f0bb9..000000000 --- a/lib/include/srsran/common/basic_pnf.h +++ /dev/null @@ -1,549 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_BASIC_PNF_H -#define SRSRAN_BASIC_PNF_H - -#include "basic_vnf_api.h" -#include "common.h" -#include "srsran/adt/choice_type.h" -#include "srsran/common/block_queue.h" -#include "srsran/common/buffer_pool.h" -#include "srsran/srslog/srslog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RAND_SEED (12384) -#define RX_TIMEOUT_MS (500) - -#define MIN_TB_LEN (100) // MAX_TB_LEN defined in api.h - -#define PING_REQUEST_PDU 1 - -namespace srsran { - -struct pnf_metrics_t { - uint32_t avg_rtt_us; - uint32_t num_timing_errors; - uint32_t num_pdus; - uint32_t tb_size; -}; - -class srsran_basic_pnf -{ - using msg_header_t = basic_vnf_api::msg_header_t; - const static size_t buffer_size = - srsran::static_max::value; - using msg_buffer_t = std::array; - -public: - srsran_basic_pnf(const std::string& type_, - const std::string& vnf_p5_addr, - const uint16_t& vnf_p5_port, - const uint32_t& sf_interval, - const int32_t& num_sf_, - const uint32_t& tb_len_) : - running(false), - type(type_), - tti(100), ///< Random start TTI - vnf_addr(vnf_p5_addr), - vnf_port(vnf_p5_port), - sf_interval_us(sf_interval), - num_sf(num_sf_), - tb_len(tb_len_), - rand_gen(RAND_SEED), - rand_dist(MIN_TB_LEN, MAX_TB_LEN) - { - logger.set_level(srslog::basic_levels::warning); - logger.set_hex_dump_max_size(-1); - } - - ~srsran_basic_pnf() { stop(); }; - - bool start() - { - // create socket - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) { - perror("socket"); - return false; - } - - int enable = 1; -#if defined(SO_REUSEADDR) - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEADDR) failed"); - } -#endif -#if defined(SO_REUSEPORT) - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEPORT) failed"); - } -#endif - - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = inet_addr(vnf_addr.c_str()); - servaddr.sin_port = htons(vnf_port); - - // start main thread - running = true; - - if (type == "gnb") { - rx_thread = std::unique_ptr(new std::thread(&srsran_basic_pnf::dl_handler_thread, this)); - tx_thread = std::unique_ptr(new std::thread(&srsran_basic_pnf::ul_handler_thread, this)); - } else { - tx_thread = std::unique_ptr(new std::thread(&srsran_basic_pnf::ue_dl_handler_thread, this)); - } - - return true; - }; - - bool stop() - { - running = false; - - if (rx_thread) { - if (rx_thread->joinable()) { - rx_thread->join(); - } - } - - if (tx_thread) { - if (tx_thread->joinable()) { - tx_thread->join(); - } - } - - return true; - }; - - pnf_metrics_t get_metrics() - { - pnf_metrics_t tmp = metrics; - metrics = {}; - return tmp; - } - - void connect_out_rf_queue(srsran::block_queue* rf_queue_) - { - rf_out_queue = rf_queue_; - policy = bridge; - } - srsran::block_queue* get_in_rf_queue() - { - policy = bridge; - return &rf_in_queue; - } - -private: - //! Waits for DL Config or Tx Request Msg from VNF and forwards to RF - void dl_handler_thread() - { - pthread_setname_np(pthread_self(), rx_thread_name.c_str()); - - // set_rt_prio(); - - struct pollfd fd; - fd.fd = sockfd; - fd.events = POLLIN; - - std::unique_ptr rx_buffer{new msg_buffer_t{}}; - - while (running) { - // receive response - int ret = poll(&fd, 1, RX_TIMEOUT_MS); - switch (ret) { - case -1: - printf("Error occurred.\n"); - running = false; - break; - case 0: - // Timeout - printf("Error: Didn't receive response after %dms\n", RX_TIMEOUT_MS); - break; - default: - int recv_ret = recv(sockfd, rx_buffer->data(), sizeof(*rx_buffer), 0); - handle_msg(rx_buffer->data(), recv_ret); - break; - } - - std::lock_guard lock(mutex); - auto rtt = - std::chrono::duration_cast(std::chrono::steady_clock::now() - tti_start_time) - .count(); - - // TODO: add averaging - metrics.avg_rtt_us = rtt; - } - }; - - void ul_handler_thread() - { - pthread_setname_np(pthread_self(), tx_thread_name.c_str()); - - // set_rt_prio(); - - struct pollfd fd; - fd.fd = sockfd; - fd.events = POLLIN; - - const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_conf_msg_t) + 32; // larger than biggest message - std::unique_ptr > rx_buffer = - std::unique_ptr >(new std::array); - - int32_t sf_counter = 0; - while (running && (num_sf > 0 ? sf_counter < num_sf : true)) { - { - std::lock_guard lock(mutex); - - // Increase TTI - tti = (tti + 1) % 10240; - - // Take time before sending the SF indication - tti_start_time = std::chrono::steady_clock::now(); - - // Send request - send_sf_ind(tti); - - if (policy == bridge) { - // send_rx_data_ind(tti); - } else { - // provide UL data every 2nd TTI - if (tti % 2 == 0) { - send_rx_data_ind(tti); - } - } - - sf_counter++; - } - - std::this_thread::sleep_for(std::chrono::microseconds(sf_interval_us)); - } - - printf("Leaving Tx thread after %d subframes\n", sf_counter); - }; - - void ue_dl_handler_thread() - { - pthread_setname_np(pthread_self(), tx_thread_name.c_str()); - - // set_rt_prio(); - - struct pollfd fd; - fd.fd = sockfd; - fd.events = POLLIN; - - const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_conf_msg_t) + 32; // larger than biggest message - std::unique_ptr > rx_buffer = - std::unique_ptr >(new std::array); - - int32_t sf_counter = 0; - while (running && (num_sf > 0 ? sf_counter < num_sf : true)) { - { - std::lock_guard lock(mutex); - - // Increase TTI - tti = (tti + 1) % 10240; - - // Take time before sending the SF indication - tti_start_time = std::chrono::steady_clock::now(); - - // Send SF indication - send_sf_ind(tti); - - if (policy == bridge) { - srsran::unique_byte_buffer_t tb; - if (rf_in_queue.try_pop(&tb)) { - send_dl_ind(tti, std::move(tb)); - } - } else { - // provide DL grant every even TTI, and UL grant every odd - if (tti % 2 == 0) { - send_dl_ind(tti); - } else { - send_ul_ind(tti); - } - } - - sf_counter++; - } - - std::this_thread::sleep_for(std::chrono::microseconds(sf_interval_us)); - } - - printf("Leaving Tx thread after %d subframes\n", sf_counter); - }; - - void send_sf_ind(uint32_t tti_) - { - basic_vnf_api::sf_ind_msg_t sf_ind; - bzero(&sf_ind, sizeof(sf_ind)); - sf_ind.header.type = basic_vnf_api::SF_IND; - sf_ind.header.msg_len = sizeof(sf_ind) - sizeof(basic_vnf_api::msg_header_t); - sf_ind.tti = tti_; - sf_ind.t1 = 0; - sf_ind.tb_len = tb_len > 0 ? tb_len : rand_dist(rand_gen); - - int n = 0; - if ((n = sendto(sockfd, &sf_ind, sizeof(sf_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) { - printf("sendto failed, ret=%d\n", n); - } - } - - int handle_msg(const uint8_t* buffer, const uint32_t len) - { - basic_vnf_api::msg_header_t* header = (basic_vnf_api::msg_header_t*)buffer; - - logger.debug("Received %s (%d B) in TTI", basic_vnf_api::msg_type_text[header->type], len); - - switch (header->type) { - case basic_vnf_api::SF_IND: - printf("Error: %s not handled by VNF\n", basic_vnf_api::msg_type_text[header->type]); - break; - case basic_vnf_api::DL_CONFIG: - handle_dl_config((basic_vnf_api::dl_conf_msg_t*)header); - break; - case basic_vnf_api::TX_REQUEST: - handle_tx_request((basic_vnf_api::tx_request_msg_t*)header); - break; - default: - printf("Unknown msg type.\n"); - break; - } - return 0; - } - - int handle_dl_config(basic_vnf_api::dl_conf_msg_t* msg) - { - // printf("Received DL config for TTI=%d\n", msg->tti); - - if (msg->tti != tti) { - metrics.num_timing_errors++; - // printf("Received DL config for TTI=%d but current TTI is %d\n", msg->tti, tti.load()); - return -1; - } - - return 0; - } - - int handle_tx_request(basic_vnf_api::tx_request_msg_t* msg) - { - if (msg->tti != tti) { - metrics.num_timing_errors++; - } - - for (uint32_t i = 0; i < msg->nof_pdus; ++i) { - metrics.tb_size += msg->pdus[i].length; - } - - metrics.num_pdus += msg->nof_pdus; - - if (rf_out_queue != nullptr) { - uint32_t len = sizeof(*msg) - sizeof(msg->pdus->data) + msg->pdus->length; - - srsran::unique_byte_buffer_t tx = srsran::make_byte_buffer(); - if (tx == nullptr) { - return -1; - } - memcpy(tx->msg, msg, len); - rf_out_queue->push(std::move(tx)); - } - - return 0; - } - - void send_rx_data_ind(const uint32_t tti_) - { - // MAC PDU for UL-SCH with IPv6 router solicitation - static uint8_t tv[] = {0x04, 0x38, 0x00, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff, 0xfe, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x44, 0x4b, 0x0f, 0x2c, 0x33, 0x98, 0xf2, - 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x85, 0x00, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7f, 0x00, 0x00, 0x3f, 0x00}; - - basic_vnf_api::rx_data_ind_msg_t rx_ind = {}; - - rx_ind.header.type = basic_vnf_api::RX_DATA_IND; - rx_ind.header.msg_len = sizeof(rx_ind) - sizeof(basic_vnf_api::msg_header_t); - rx_ind.sfn = tti_; - rx_ind.t1 = 0; - - rx_ind.nof_pdus = 1; - rx_ind.pdus[0].type = basic_vnf_api::PUSCH; - rx_ind.pdus[0].length = tb_len > 0 ? tb_len : rand_dist(rand_gen); - - if (rx_ind.pdus[0].length >= sizeof(tv)) { - // copy TV - memcpy(rx_ind.pdus[0].data, tv, sizeof(tv)); - // set remaining bytes to zero - memset(rx_ind.pdus[0].data + sizeof(tv), 0xaa, rx_ind.pdus[0].length - sizeof(tv)); - } else { - // just fill with dummy bytes - memset(rx_ind.pdus[0].data, 0xab, rx_ind.pdus[0].length); - } - - int n = 0; - if ((n = sendto(sockfd, &rx_ind, sizeof(rx_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) { - printf("sendto failed, ret=%d\n", n); - } - } - - void send_dl_ind(uint32_t tti_, srsran::unique_byte_buffer_t tb = {}) - { -#if PING_REQUEST_PDU - static uint8_t tv[] = { - 0x04, 0x5c, 0x00, 0x80, 0x00, 0x00, 0x45, 0x00, 0x00, 0x54, 0x15, 0x02, 0x40, 0x00, 0x40, 0x01, 0xa2, 0x52, - 0xc0, 0xa8, 0x01, 0x01, 0xc0, 0xa8, 0x01, 0x03, 0x08, 0x00, 0x26, 0x40, 0x5e, 0x8f, 0x00, 0xb3, 0x04, 0x55, - 0xc4, 0x5d, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x4f, 0x7f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -#else - // MAC PDU with a single LCID with padding only - static uint8_t tv[] = { - 0x01, - 0x08, - 0x11, - 0x22, - 0x33, - 0x44, - 0x55, - 0x66, - 0x77, - 0x88, - 0x3f, - }; -#endif // PING_REQUEST_PDU - basic_vnf_api::dl_ind_msg_t dl_ind = {}; - - dl_ind.header.type = basic_vnf_api::DL_IND; - dl_ind.header.msg_len = sizeof(dl_ind) - sizeof(basic_vnf_api::msg_header_t); - dl_ind.tti = tti_; - dl_ind.t1 = 0; - - uint32_t tot_bytes = 0; - uint32_t tb_size = tb_len > 0 ? tb_len : rand_dist(rand_gen); - - if (tb != nullptr) { - auto* header = (basic_vnf_api::msg_header_t*)tb->msg; - - if (header->type == basic_vnf_api::TX_REQUEST) { - auto* tx_req = (basic_vnf_api::tx_request_msg_t*)tb->msg; - dl_ind.nof_pdus = tx_req->nof_pdus; - // dl_ind.tti = tx_req->tti; - for (uint32_t i = 0; i < dl_ind.nof_pdus; ++i) { - dl_ind.pdus[i].length = tx_req->pdus[i].length; - dl_ind.pdus[i].type = tx_req->pdus[i].type; - memcpy(dl_ind.pdus[i].data, tx_req->pdus[i].data, dl_ind.pdus[i].length); - tot_bytes += dl_ind.pdus[i].length; - logger.info( - dl_ind.pdus[i].data, dl_ind.pdus[i].length, "Sending to UE a PDU (%d bytes)", dl_ind.pdus[i].length); - } - } - } else { - uint32_t N_bytes = sizeof(tv); - - // Create default - dl_ind.nof_pdus = 1; - dl_ind.pdus[0].type = basic_vnf_api::PDSCH; - dl_ind.pdus[0].length = tb_size; - - if (dl_ind.pdus[0].length >= N_bytes) { - // copy TV - memcpy(dl_ind.pdus[0].data, tv, N_bytes); - tot_bytes = N_bytes; - } - - logger.info(dl_ind.pdus[0].data, N_bytes, "Sending to UE a TB (%d bytes)", N_bytes); - } - - if (tot_bytes > 0 and tot_bytes < tb_size) { - uint8_t* offset = &dl_ind.pdus[dl_ind.nof_pdus - 1].data[dl_ind.pdus[dl_ind.nof_pdus - 1].length]; - memset(offset, 0xaa, tb_size - tot_bytes); - } else if (tot_bytes == 0) { - // just fill with dummy bytes - dl_ind.nof_pdus = 1; - memset(dl_ind.pdus[0].data, 0xab, tb_size); - } - - int n = 0; - if ((n = sendto(sockfd, &dl_ind, sizeof(dl_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) { - printf("sendto failed, ret=%d\n", n); - } - } - - void send_ul_ind(uint32_t tti_) - { - basic_vnf_api::ul_ind_msg_t ul_ind = {}; - - ul_ind.header.type = basic_vnf_api::UL_IND; - ul_ind.header.msg_len = sizeof(ul_ind) - sizeof(basic_vnf_api::msg_header_t); - ul_ind.tti = tti_; - ul_ind.t1 = 0; - - ul_ind.pdus.type = basic_vnf_api::PUSCH; - ul_ind.pdus.length = tb_len > 0 ? tb_len : rand_dist(rand_gen); - - int n = 0; - if ((n = sendto(sockfd, &ul_ind, sizeof(ul_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) { - printf("sendto failed, ret=%d\n", n); - } - } - - std::unique_ptr tx_thread, rx_thread; - std::string tx_thread_name = "TX_PNF", rx_thread_name = "RX_PNF"; - bool running = false; - srslog::basic_logger& logger = srslog::fetch_basic_logger("PNF", false); - - std::mutex mutex; - std::atomic tti; - std::chrono::steady_clock::time_point tti_start_time; - - std::string type; - - std::string vnf_addr; - uint16_t vnf_port = 3333; - - uint32_t sf_interval_us = 1000; - int32_t num_sf = -1; - uint32_t tb_len = 100; - - pnf_metrics_t metrics = {}; - - int sockfd = 0; - struct sockaddr_in servaddr = {}; - - // For random number generation - std::mt19937 rand_gen; - std::uniform_int_distribution rand_dist; - - // two policies possible: dummy packets generated by the PNF class, or bridge between UE and gNB PNFs with TBs - // entering/exiting each PNF via the rf_in_queue/rf_out_queue. - srsran::block_queue* rf_out_queue = nullptr; - srsran::block_queue rf_in_queue; - enum data_policy_t { self_gen, bridge } policy = self_gen; -}; - -} // namespace srsran - -#endif // SRSRAN_BASIC_PNF_H diff --git a/lib/include/srsran/common/basic_vnf.h b/lib/include/srsran/common/basic_vnf.h deleted file mode 100644 index b72748a0d..000000000 --- a/lib/include/srsran/common/basic_vnf.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_BASIC_VNF_H -#define SRSRAN_BASIC_VNF_H - -#include "basic_vnf_api.h" -#include "common.h" -#include "srsran/common/threads.h" -#include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/ue_nr_interfaces.h" -#include "srsran/srslog/srslog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace srsran { - -class srsran_basic_vnf : public thread -{ -public: - srsran_basic_vnf(const vnf_args_t& args_, stack_interface_phy_nr* stack_); - ~srsran_basic_vnf(); - - bool stop(); - - int dl_config_request(const srsenb::phy_interface_stack_nr::dl_config_request_t& request); - int tx_request(const srsenb::phy_interface_stack_nr::tx_request_t& request); - int tx_request(const srsue::phy_interface_stack_nr::tx_request_t& request); - -private: - void run_thread(); - - // handlers - int handle_msg(const uint8_t* buffer, const uint32_t len); - int handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg); - int handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg); - int handle_ul_ind(basic_vnf_api::ul_ind_msg_t* msg); - int handle_rx_data_ind(basic_vnf_api::rx_data_ind_msg_t* msg); - - // senders - int send_dl_config_request(); - - // helpers - uint32_t calc_full_msg_len(const basic_vnf_api::tx_request_msg_t& msg); - - srslog::basic_logger& logger = srslog::fetch_basic_logger("VNF", false); - srsenb::stack_interface_phy_nr* m_gnb_stack = nullptr; - srsue::stack_interface_phy_nr* m_ue_stack = nullptr; - - std::unique_ptr m_tx_req_msg; - - bool running = false; - - vnf_args_t m_args = {}; - - int sockfd = 0; - struct sockaddr_in servaddr = {}, client_addr = {}; - - uint32_t last_sf_indication_time = 0; -}; - -} // namespace srsran - -#endif // SRSRAN_BASIC_VNF_H diff --git a/lib/include/srsran/common/basic_vnf_api.h b/lib/include/srsran/common/basic_vnf_api.h deleted file mode 100644 index 9a14a8793..000000000 --- a/lib/include/srsran/common/basic_vnf_api.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_BASIC_VNF_API_H -#define SRSRAN_BASIC_VNF_API_H - -#include - -namespace basic_vnf_api { - -// PNF (the PHY) VNF (the L2/L3) -// | | -// | | -// | - | -// | \ sf_ind_msg_t -// | \ | -// | \ | -// | \ | -// | \ | -// | \ | -// | \| -// | | -// | | DL_CONFIG.request -// | /| -// | / | -// | / | -// | / | -// | / | -// | / dl_conf_msg_t -// | / | -// |/ | TX.request -// | /| -// | / | -// | / | -// | / | -// | / | -// | / tx_request_msg_t -// | / | -// |/ | -// | | - -// Primitive API messages for basic testing basic VNF/PNF interaction -enum msg_type_t { - SF_IND, ///< To signal start of new subframe (later slot) for both UE and gNB - DL_CONFIG, ///< To configure the DL for gNB - TX_REQUEST, ///< For DL data for gNB - RX_DATA_IND, ///< For UL Data for gNB - DL_IND, ///< For the UE for DL data - UL_IND, ///< For the UE for UL Data - MSG_TYPE_NITEMS -}; -static const char* msg_type_text[MSG_TYPE_NITEMS] = - {"SF Indication", "DL_CONFIG.Request", "TX.Request", "RX_Data.indication", "DL_Indication", "UL_Indication"}; -enum pdu_type_t { MAC_PBCH, PHY_PBCH, PDCCH, PDSCH, PUSCH }; - -struct msg_header_t { - msg_type_t type; - uint32_t msg_len; -}; - -struct sf_ind_msg_t { - msg_header_t header; - uint32_t t1; // Timestamp taken at PNF - uint32_t tti; // TTI of requested subframe - uint32_t tb_len; // Length of the TB -}; - -#define MAX_TB_LEN (16 * 1024) -#define MAX_PDU_SIZE (16 * 1024) -#define MAX_NUM_PDUS (1) - -struct phy_pbch_pdu_t { - uint16_t phy_cell_id; // 0 - 1007 - uint8_t ss_block_index; // 0-63 - uint8_t ssb_sc_offset; // 0-15 - uint8_t dmrs_pos; // 0-1 - uint8_t pdcch_config; // 0-255 -}; - -struct dl_conf_msg_t { - msg_header_t header; - uint32_t t1; // Replayed timestamp - uint32_t t2; // Timestamp taken at VNF - uint32_t tti; // TTI - uint16_t beam_id; // tx beam id for the slot -}; - -struct tx_request_pdu_t { - uint16_t length; - uint16_t index; // index indicated in dl_config - pdu_type_t type; // physical chan of pdu/tb - uint8_t data[MAX_PDU_SIZE]; -}; - -struct tx_request_msg_t { - msg_header_t header; - uint32_t tti; // TTI - uint32_t tb_len; // actual TB len - uint32_t nof_pdus; - tx_request_pdu_t pdus[MAX_NUM_PDUS]; -}; - -struct rx_data_ind_pdu_t { - uint16_t length; - pdu_type_t type; // physical chan of pdu/tb - uint8_t data[MAX_PDU_SIZE]; -}; - -struct rx_data_ind_msg_t { - msg_header_t header; - uint32_t t1; // Timestamp taken at PNF - uint32_t sfn; ///< SFN (0-1023) - uint32_t slot; ///< Slot (0-319) - uint32_t tb_len; ///< actual TB len - uint32_t nof_pdus; // - rx_data_ind_pdu_t pdus[MAX_NUM_PDUS]; -}; - -// UE specific messages -struct dl_ind_pdu_t { - pdu_type_t type; // physical chan of pdu/tb - uint16_t length; - uint8_t data[MAX_PDU_SIZE]; -}; - -struct dl_ind_msg_t { - msg_header_t header; - uint32_t t1; // Timestamp taken at PNF - uint32_t tti; // tti or slot? - uint32_t nof_pdus; - dl_ind_pdu_t pdus[MAX_NUM_PDUS]; -}; - -///< Messages for UL (only one PDU) -struct ul_ind_pdu_t { - pdu_type_t type; // physical chan of pdu/tb - uint16_t length; -}; - -struct ul_ind_msg_t { - msg_header_t header; - uint32_t t1; // Timestamp taken at PNF - uint32_t tti; // tti or slot? - uint32_t rnti; ///< RNTI of this grant - ul_ind_pdu_t pdus; -}; - -} // namespace basic_vnf_api - -#endif // SRSRAN_BASIC_VNF_API_H diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 8c0f15aa0..12a78d129 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -34,8 +34,7 @@ set(SOURCES arch_select.cc time_prof.cc version.c zuc.cc - s3g.cc - basic_vnf.cc) + s3g.cc) # Avoid warnings caused by libmbedtls about deprecated functions set_source_files_properties(security.cc PROPERTIES COMPILE_FLAGS -Wno-deprecated-declarations) diff --git a/lib/src/common/basic_vnf.cc b/lib/src/common/basic_vnf.cc deleted file mode 100644 index be8a609e9..000000000 --- a/lib/src/common/basic_vnf.cc +++ /dev/null @@ -1,399 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include "srsran/common/basic_vnf.h" -#include "srsran/common/buffer_pool.h" -#include "srsran/interfaces/ue_nr_interfaces.h" -#include -#include -#include - -#define RAND_SEED (12314) -#define RX_TIMEOUT_MS (1000) - -namespace srsran { - -struct srsran_pnf_info_t { - // TODO: fill when needed -}; - -struct srsran_vnf_info_t {}; - -srsran_basic_vnf::srsran_basic_vnf(const vnf_args_t& args_, stack_interface_phy_nr* stack_) : - m_args(args_), thread("BASIC_VNF_P7"), m_tx_req_msg(new basic_vnf_api::tx_request_msg_t) -{ - logger.set_level(srslog::str_to_basic_level(m_args.log_level)); - logger.set_hex_dump_max_size(m_args.log_hex_limit); - - if (m_args.type == "gnb" || m_args.type == "ue") { - if (m_args.type == "gnb") { - m_gnb_stack = (srsenb::stack_interface_phy_nr*)stack_; - } else { - m_ue_stack = (srsue::stack_interface_phy_nr*)stack_; - } - - logger.info("Initializing VNF for gNB"); - start(); - } else { - logger.error("Unknown VNF type. Exiting."); - } -} - -srsran_basic_vnf::~srsran_basic_vnf() -{ - stop(); -} - -void srsran_basic_vnf::run_thread() -{ - // Bind to UDP socket - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) { - perror("socket"); - return; - } - - // Make sockets reusable - int enable = 1; -#if defined(SO_REUSEADDR) - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEADDR) failed"); - } -#endif -#if defined(SO_REUSEPORT) - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) { - perror("setsockopt(SO_REUSEPORT) failed"); - } -#endif - - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(m_args.bind_port); - - if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))) { - perror("bind"); - return; - } - - struct pollfd fd; - fd.fd = sockfd; - fd.events = POLLIN; - - const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_ind_msg_t) + 32; // larger than biggest message - std::unique_ptr > rx_buffer = - std::unique_ptr >(new std::array); - - running = true; - - logger.info("Started VNF handler listening on %s:%d", m_args.bind_addr.c_str(), m_args.bind_port); - - while (running) { - int ret = poll(&fd, 1, RX_TIMEOUT_MS); - switch (ret) { - case -1: - printf("Error occured.\n"); - break; - case 0: - // Timeout - break; - default: - - socklen_t len = sizeof(client_addr); - ret = recvfrom(sockfd, rx_buffer->data(), rx_buffer->size(), MSG_WAITALL, (struct sockaddr*)&client_addr, &len); - - handle_msg(rx_buffer->data(), ret); - break; - } - } - logger.info("VNF thread stopped"); -} - -int srsran_basic_vnf::handle_msg(const uint8_t* buffer, const uint32_t len) -{ - basic_vnf_api::msg_header_t* header = (basic_vnf_api::msg_header_t*)buffer; - - logger.info("Received %s (%d B)", basic_vnf_api::msg_type_text[header->type], len); - - switch (header->type) { - case basic_vnf_api::SF_IND: - handle_sf_ind((basic_vnf_api::sf_ind_msg_t*)header); - break; - case basic_vnf_api::DL_CONFIG: - printf("Error: %s not handled by VNF\n", basic_vnf_api::msg_type_text[header->type]); - break; - case basic_vnf_api::DL_IND: - handle_dl_ind((basic_vnf_api::dl_ind_msg_t*)header); - break; - case basic_vnf_api::UL_IND: - handle_ul_ind((basic_vnf_api::ul_ind_msg_t*)header); - break; - case basic_vnf_api::RX_DATA_IND: - handle_rx_data_ind((basic_vnf_api::rx_data_ind_msg_t*)header); - break; - default: - printf("Unknown msg type.\n"); - break; - } - return 0; -} - -int srsran_basic_vnf::handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg) -{ - int ret = SRSRAN_SUCCESS; - logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti); - - // store Rx timestamp - last_sf_indication_time = msg->t1; - - if (m_gnb_stack != nullptr) { - srsran_slot_cfg_t slot_cfg = {}; - slot_cfg.idx = msg->tti; - m_gnb_stack->slot_indication(slot_cfg); - } else if (m_ue_stack != nullptr) { - m_ue_stack->sf_indication(msg->tti); - } else { - ret = SRSRAN_ERROR; - } - - return ret; -} - -int srsran_basic_vnf::handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg) -{ - int ret = SRSRAN_ERROR; - logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti); - - uint32_t cc_idx = 0; - - // fill DL struct - srsue::stack_interface_phy_nr::mac_nr_grant_dl_t dl_grant = {}; - dl_grant.tti = msg->tti; - - if (msg->nof_pdus > SRSRAN_MAX_TB) { - logger.error("Too many TBs (%d > %d)", msg->nof_pdus, SRSRAN_MAX_TB); - goto exit; - } - - for (uint32_t i = 0; i < msg->nof_pdus; ++i) { - srsue::stack_interface_phy_nr::tb_action_dl_result_t result = {}; - result.payload = srsran::make_byte_buffer(); - if (result.payload != nullptr && result.payload->get_tailroom() >= msg->pdus[i].length) { - result.ack = true; - memcpy(result.payload->msg, msg->pdus[i].data, msg->pdus[i].length); - result.payload->N_bytes = msg->pdus[i].length; - if (msg->pdus[i].type == basic_vnf_api::PDSCH) { - m_ue_stack->tb_decoded(cc_idx, dl_grant, std::move(result)); - } - } else { - logger.error("TB too big to fit into buffer (%d)", msg->pdus[i].length); - return SRSRAN_ERROR; - } - } - - ret = SRSRAN_SUCCESS; - -exit: - - return ret; -} - -int srsran_basic_vnf::handle_ul_ind(basic_vnf_api::ul_ind_msg_t* msg) -{ - logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti); - - if (msg->pdus.type != basic_vnf_api::PUSCH) { - logger.error("Received UL indication for wrong PDU type"); - return SRSRAN_ERROR; - } - - uint32_t cc_idx = 0; - - // fill DL struct - srsue::stack_interface_phy_nr::mac_nr_grant_ul_t ul_grant = {}; - ul_grant.tti = msg->tti; - ul_grant.tbs = msg->pdus.length; - ul_grant.rnti = msg->rnti; - - srsue::stack_interface_phy_nr::tb_action_ul_t ul_action = {}; - m_ue_stack->new_grant_ul(cc_idx, ul_grant, &ul_action); - - return SRSRAN_SUCCESS; -} - -int srsran_basic_vnf::handle_rx_data_ind(basic_vnf_api::rx_data_ind_msg_t* msg) -{ - logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->sfn); - - if (msg->nof_pdus != 1 || msg->pdus[0].type != basic_vnf_api::PUSCH) { - logger.error("Received UL indication for wrong PDU type"); - return SRSRAN_ERROR; - } - - // fill struct - srsenb::stack_interface_phy_nr::rx_data_ind_t rx_data = {}; - rx_data.tti = msg->sfn; - rx_data.tb = srsran::make_byte_buffer(); - if (rx_data.tb->get_tailroom() >= msg->pdus[0].length) { - // copy actual data - memcpy(rx_data.tb->msg, msg->pdus[0].data, msg->pdus[0].length); - rx_data.tb->N_bytes = msg->pdus[0].length; - if (msg->pdus[0].type == basic_vnf_api::PUSCH) { - m_gnb_stack->rx_data_indication(rx_data); - } - } - - return SRSRAN_SUCCESS; -} - -int srsran_basic_vnf::dl_config_request(const srsenb::phy_interface_stack_nr::dl_config_request_t& request) -{ - // Generate DL Config - basic_vnf_api::dl_conf_msg_t dl_conf = {}; - dl_conf.header.type = basic_vnf_api::DL_CONFIG; - dl_conf.header.msg_len = sizeof(dl_conf) - sizeof(basic_vnf_api::msg_header_t); - - dl_conf.t1 = last_sf_indication_time; // play back the time - dl_conf.t2 = 0xaa; // TODO: add timestamp - dl_conf.tti = request.tti; - dl_conf.beam_id = request.beam_id; - - // Send entire struct - uint32_t len = sizeof(dl_conf); - - // Send it to PNF - logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[dl_conf.header.type], len); - int n = 0; - if ((n = sendto(sockfd, &dl_conf, len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) < 0) { - logger.error("sendto failed, ret=%d", n); - } - - return 0; -} - -/// Tx request from UE, i.e. UL transmission -int srsran_basic_vnf::tx_request(const srsue::phy_interface_stack_nr::tx_request_t& request) -{ - // Generate Tx request - m_tx_req_msg->header.type = basic_vnf_api::TX_REQUEST; - m_tx_req_msg->header.msg_len = 0; // set further down - - m_tx_req_msg->tti = request.tti; - - m_tx_req_msg->nof_pdus = 1; - m_tx_req_msg->pdus[0].index = 0; - m_tx_req_msg->pdus[0].type = basic_vnf_api::PUSCH; - m_tx_req_msg->pdus[0].length = request.tb_len; - - if (request.tb_len <= MAX_PDU_SIZE) { - // copy data from TB0 - memcpy(m_tx_req_msg->pdus[0].data, request.data, request.tb_len); - } else { - logger.error("Trying to send %d B PDU. Maximum size is %d B", request.tb_len, MAX_PDU_SIZE); - } - - // calculate actual length of - uint32_t len = calc_full_msg_len(*m_tx_req_msg.get()); - - // update msg header length field - m_tx_req_msg->header.msg_len = len - sizeof(basic_vnf_api::msg_header_t); - - // Send it to PNF - logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[m_tx_req_msg->header.type], len); - int n = 0; - if ((n = sendto(sockfd, m_tx_req_msg.get(), len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) < - 0) { - logger.error("sendto failed, ret=%d", n); - } - - return 0; -} - -int srsran_basic_vnf::tx_request(const srsenb::phy_interface_stack_nr::tx_request_t& request) -{ - if (request.nof_pdus > MAX_NUM_PDUS) { - logger.error("Trying to send %d PDUs but only %d supported", request.nof_pdus, MAX_NUM_PDUS); - return SRSRAN_ERROR; - } - if (request.nof_pdus == 0) { - return SRSRAN_SUCCESS; - } - - // Generate Tx request - m_tx_req_msg->header.type = basic_vnf_api::TX_REQUEST; - m_tx_req_msg->header.msg_len = 0; // set further down - - m_tx_req_msg->nof_pdus = request.nof_pdus; - m_tx_req_msg->tti = request.tti; - - for (uint32_t i = 0; i < m_tx_req_msg->nof_pdus; ++i) { - if (request.pdus[i].length <= MAX_PDU_SIZE) { - m_tx_req_msg->pdus[i].index = i; - m_tx_req_msg->pdus[i].type = request.pdus[i].pbch.mib_present ? basic_vnf_api::MAC_PBCH : basic_vnf_api::PDSCH; - m_tx_req_msg->pdus[i].length = request.pdus[i].length; - // copy data from TB0 - memcpy(m_tx_req_msg->pdus[i].data, request.pdus[i].data[0], m_tx_req_msg->pdus[i].length); - } else { - logger.error("Trying to send %d B PDU. Maximum size is %d B", request.pdus[i].length, MAX_PDU_SIZE); - } - } - - // calculate actual length of message - uint32_t len = calc_full_msg_len(*m_tx_req_msg.get()); - - // update msg header length field - m_tx_req_msg->header.msg_len = len - sizeof(basic_vnf_api::msg_header_t); - - // Send it to PNF - logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[m_tx_req_msg->header.type], len); - if (logger.debug.enabled()) { - for (uint32_t i = 0; i < m_tx_req_msg->nof_pdus; ++i) { - logger.debug(m_tx_req_msg->pdus[i].data, - m_tx_req_msg->pdus[i].length, - "Sending PDU %s:%d (%d bytes)", - basic_vnf_api::msg_type_text[m_tx_req_msg->header.type], - m_tx_req_msg->pdus[i].index, - m_tx_req_msg->pdus[i].length); - } - } - int n = 0; - if ((n = sendto(sockfd, m_tx_req_msg.get(), len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) < - 0) { - logger.error("sendto failed, ret=%d", n); - } - - return 0; -} - -uint32_t srsran_basic_vnf::calc_full_msg_len(const basic_vnf_api::tx_request_msg_t& msg) -{ - // start with mandatory part - uint32_t len = sizeof(basic_vnf_api::msg_header_t) + 3 * sizeof(uint32_t); - - // add all PDUs - for (uint32_t i = 0; i < msg.nof_pdus; ++i) { - len += 2 * sizeof(uint16_t) + sizeof(basic_vnf_api::pdu_type_t) + msg.pdus[i].length; - } - - return len; -} - -bool srsran_basic_vnf::stop() -{ - if (running) { - running = false; - wait_thread_finish(); - } - - return true; -} - -} // namespace srsran diff --git a/lib/test/common/CMakeLists.txt b/lib/test/common/CMakeLists.txt index 1b731e167..66b9576ff 100644 --- a/lib/test/common/CMakeLists.txt +++ b/lib/test/common/CMakeLists.txt @@ -73,11 +73,5 @@ add_executable(task_scheduler_test task_scheduler_test.cc) target_link_libraries(task_scheduler_test srsran_common ${ATOMIC_LIBS}) add_test(task_scheduler_test task_scheduler_test) -add_executable(pnf_dummy pnf_dummy.cc) -target_link_libraries(pnf_dummy srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) - -add_executable(pnf_bridge pnf_bridge.cc) -target_link_libraries(pnf_bridge srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) - add_executable(mac_pcap_net_test mac_pcap_net_test.cc) target_link_libraries(mac_pcap_net_test srsran_common ${SCTP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/lib/test/common/pnf_bridge.cc b/lib/test/common/pnf_bridge.cc deleted file mode 100644 index 60dd56b48..000000000 --- a/lib/test/common/pnf_bridge.cc +++ /dev/null @@ -1,118 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "srsran/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(1600), "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); - - srsran::srsran_basic_pnf ue_pnf("ue", args.ue_vnf_addr, args.ue_vnf_port, args.sf_interval, args.num_sf, args.tb_len); - srsran::srsran_basic_pnf gnb_pnf( - "gnb", args.gnb_vnf_addr, args.gnb_vnf_port, args.sf_interval, args.num_sf, args.tb_len); - - gnb_pnf.connect_out_rf_queue(ue_pnf.get_in_rf_queue()); - - ue_pnf.start(); - gnb_pnf.start(); - - while (running) { - for (uint32_t i = 0; i < 2; ++i) { - srsran::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 / 1.0e6); - } - - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - ue_pnf.stop(); - gnb_pnf.stop(); - - return 0; -} \ No newline at end of file diff --git a/lib/test/common/pnf_dummy.cc b/lib/test/common/pnf_dummy.cc deleted file mode 100644 index f61d26b2d..000000000 --- a/lib/test/common/pnf_dummy.cc +++ /dev/null @@ -1,108 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "srsran/common/basic_pnf.h" - -using namespace std; -namespace bpo = boost::program_options; - -struct pnf_args_t { - std::string type; - std::string vnf_addr; - uint16_t 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.type", bpo::value(&args->type)->default_value("gnb"), "VNF instance type [gnb,ue]") - ("vnf.addr", bpo::value(&args->vnf_addr)->default_value("127.0.0.1"), "VNF address") - ("vnf.port", bpo::value(&args->vnf_port)->default_value(3333), "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); - - srsran::srsran_basic_pnf pnf(args.type, args.vnf_addr, args.vnf_port, args.sf_interval, args.num_sf, args.tb_len); - - pnf.start(); - - while (running) { - srsran::pnf_metrics_t metrics = pnf.get_metrics(); - printf("RTT=%d, #Error=%d, #PDUs=%d, Total TB size=%d, Rate=%.2f Mbit/s\n", - 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)); - } - - pnf.stop(); - - return 0; -} \ No newline at end of file diff --git a/srsenb/hdr/phy/vnf_phy_nr.h b/srsenb/hdr/phy/vnf_phy_nr.h deleted file mode 100644 index 1be7633b8..000000000 --- a/srsenb/hdr/phy/vnf_phy_nr.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSGNB_NR_VNF_PHY_H -#define SRSGNB_NR_VNF_PHY_H - -#include "srsenb/hdr/phy/enb_phy_base.h" -#include "srsenb/hdr/phy/phy_common.h" -#include "srsran/common/basic_vnf.h" -#include "srsran/interfaces/enb_metrics_interface.h" -#include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/radio_interfaces.h" - -namespace srsenb { - -struct nr_phy_cfg_t { - // TODO: add cell and RRC configs -}; - -class vnf_phy_nr : public srsenb::enb_phy_base, public srsenb::phy_interface_stack_nr -{ -public: - vnf_phy_nr() = default; - ~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() override; - - std::string get_type() override { return "vnf"; }; - - void start_plot() override; - - void get_metrics(std::vector& metrics) override; - - // MAC interface - 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: - std::unique_ptr vnf = nullptr; - - bool initialized = false; - - void parse_config(const nr_phy_cfg_t& cfg); -}; - -} // namespace srsenb - -#endif // SRSGNB_NR_VNF_PHY_H diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index e5a3c6f03..166c6e72e 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -29,7 +29,7 @@ add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_js set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system) set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_gtpu srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system) -set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) +set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) target_link_libraries(srsenb ${SRSENB_SOURCES} diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 1d81bc0e9..fd6e66e2b 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -11,7 +11,6 @@ */ #include "srsenb/hdr/enb.h" -#include "srsenb/hdr/phy/vnf_phy_nr.h" #include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/stack/gnb_stack_nr.h" #include "srsenb/src/enb_cfg_parser.h" @@ -95,40 +94,9 @@ int enb::init(const all_args_t& args_) phy = std::move(lte_phy); radio = std::move(lte_radio); - } else if (args.stack.type == "nr") { - std::unique_ptr nr_stack(new srsenb::gnb_stack_nr); - std::unique_ptr nr_radio(new srsran::radio_null); - std::unique_ptr nr_phy(new srsenb::vnf_phy_nr); - - // Init layers - if (nr_radio->init(args.rf, nullptr)) { - srsran::console("Error initializing radio.\n"); - return SRSRAN_ERROR; - } - - // TODO: where do we put this? - srsenb::nr_phy_cfg_t nr_phy_cfg = {}; - - args.phy.vnf_args.type = "gnb"; - args.phy.vnf_args.log_level = args.phy.log.phy_level; - args.phy.vnf_args.log_hex_limit = args.phy.log.phy_hex_limit; - if (nr_phy->init(args.phy, nr_phy_cfg, nr_stack.get())) { - srsran::console("Error initializing PHY.\n"); - return SRSRAN_ERROR; - } - - // Same here, where do we put this? - srsenb::rrc_nr_cfg_t rrc_nr_cfg = {}; - rrc_nr_cfg.coreless = args.stack.coreless; - - if (nr_stack->init(args.stack, rrc_nr_cfg, nr_phy.get())) { - srsran::console("Error initializing stack.\n"); - return SRSRAN_ERROR; - } - - stack = std::move(nr_stack); - phy = std::move(nr_phy); - radio = std::move(nr_radio); + } else { + srsran::console("Stack type %s not supported.\n", args.stack.type.c_str()); + return SRSRAN_ERROR; } started = true; // set to true in any case to allow stopping the eNB if an error happened diff --git a/srsenb/src/phy/CMakeLists.txt b/srsenb/src/phy/CMakeLists.txt index 66c4db7b2..9ef998da7 100644 --- a/srsenb/src/phy/CMakeLists.txt +++ b/srsenb/src/phy/CMakeLists.txt @@ -19,8 +19,6 @@ set(SOURCES txrx.cc) add_library(srsenb_phy STATIC ${SOURCES}) -add_library(srsgnb_phy STATIC vnf_phy_nr.cc) - if (ENABLE_GUI AND SRSGUI_FOUND) target_link_libraries(srsenb_phy ${SRSGUI_LIBRARIES}) endif () diff --git a/srsenb/src/phy/vnf_phy_nr.cc b/srsenb/src/phy/vnf_phy_nr.cc deleted file mode 100644 index 5d5a3f608..000000000 --- a/srsenb/src/phy/vnf_phy_nr.cc +++ /dev/null @@ -1,67 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include -#include - -#include "srsenb/hdr/phy/vnf_phy_nr.h" -#include "srsran/common/basic_vnf_api.h" - -using namespace std; - -namespace srsenb { - -vnf_phy_nr::~vnf_phy_nr() -{ - stop(); -} - -void vnf_phy_nr::parse_config(const nr_phy_cfg_t& cfg) {} - -int vnf_phy_nr::init(const srsenb::phy_args_t& args, const nr_phy_cfg_t& cfg, srsenb::stack_interface_phy_nr* stack_) -{ - mlockall(MCL_CURRENT | MCL_FUTURE); - - // create VNF - vnf = std::unique_ptr(new srsran::srsran_basic_vnf(args.vnf_args, stack_)); - - initialized = true; - - return SRSRAN_SUCCESS; -} - -void vnf_phy_nr::stop() -{ - if (initialized) { - vnf->stop(); - initialized = false; - } -} - -// Start GUI -void vnf_phy_nr::start_plot() {} - -void vnf_phy_nr::get_metrics(std::vector& metrics) {} - -int vnf_phy_nr::dl_config_request(const dl_config_request_t& request) -{ - // prepare DL config request over basic API and send - return vnf->dl_config_request(request); -} - -int vnf_phy_nr::tx_request(const tx_request_t& request) -{ - // send Tx request over basic API - return vnf->tx_request(request); -} - -} // namespace srsenb diff --git a/srsue/hdr/phy/vnf_phy_nr.h b/srsue/hdr/phy/vnf_phy_nr.h deleted file mode 100644 index a09f5568e..000000000 --- a/srsue/hdr/phy/vnf_phy_nr.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSUE_VNF_PHY_NR_H -#define SRSUE_VNF_PHY_NR_H - -#include "srsenb/hdr/phy/phy_common.h" -#include "srsran/common/basic_vnf.h" -#include "srsran/interfaces/enb_metrics_interface.h" -#include "srsran/interfaces/radio_interfaces.h" -#include "srsran/interfaces/ue_interfaces.h" -#include "srsran/interfaces/ue_nr_interfaces.h" -#include "srsue/hdr/phy/ue_nr_phy_base.h" - -namespace srsue { - -class vnf_phy_nr : public srsue::ue_phy_base, public srsue::phy_interface_stack_nr -{ -public: - vnf_phy_nr() = default; - ~vnf_phy_nr(); - - int init(const srsue::phy_args_t& args, srsue::stack_interface_phy_nr* stack_); - - int init(const srsue::phy_args_t& args_) override; - - void set_earfcn(std::vector earfcns); - - void stop() override; - - void wait_initialize() override; - void get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) override; - - std::string get_type() override { return "vnf_nr"; }; - - void start_plot() override; - - // RRC interface - bool set_config(const srsran::phy_cfg_nr_t& cfg) override; - - // MAC interface - int tx_request(const tx_request_t& request) override; - int set_ul_grant(std::array, uint16_t rnti, srsran_rnti_type_t rnti_type) override - { - return SRSRAN_SUCCESS; - }; - void send_prach(const uint32_t preamble_idx, - const int prach_occasion, - const float target_power_dbm, - const float ta_base_sec = 0.0f) override{}; - bool has_valid_sr_resource(uint32_t sr_id) override; - void clear_pending_grants() override; - -private: - std::unique_ptr vnf; - - srsue::stack_interface_phy_nr* stack = nullptr; - - bool initialized = false; -}; - -} // namespace srsue - -#endif // SRSUE_VNF_PHY_NR_H diff --git a/srsue/src/phy/CMakeLists.txt b/srsue/src/phy/CMakeLists.txt index d1e45cdaf..8bc3e6f8f 100644 --- a/srsue/src/phy/CMakeLists.txt +++ b/srsue/src/phy/CMakeLists.txt @@ -13,7 +13,4 @@ add_library(srsue_phy STATIC ${SOURCES}) if(ENABLE_GUI AND SRSGUI_FOUND) target_link_libraries(srsue_phy ${SRSGUI_LIBRARIES}) -endif() - -set(SOURCES_NR "../phy/vnf_phy_nr.cc") -add_library(srsue_phy_nr STATIC ${SOURCES_NR}) +endif() \ No newline at end of file diff --git a/srsue/src/phy/vnf_phy_nr.cc b/srsue/src/phy/vnf_phy_nr.cc deleted file mode 100644 index 8b62baa86..000000000 --- a/srsue/src/phy/vnf_phy_nr.cc +++ /dev/null @@ -1,82 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "srsran/common/basic_vnf_api.h" -#include "srsran/common/test_common.h" -#include "srsran/common/threads.h" -#include "srsue/hdr/phy/vnf_phy_nr.h" - -using namespace std; - -namespace srsue { - -vnf_phy_nr::~vnf_phy_nr() -{ - stop(); -} - -int vnf_phy_nr::init(const srsue::phy_args_t& args_, srsue::stack_interface_phy_nr* stack_) -{ - stack = stack_; - return init(args_); -} - -int vnf_phy_nr::init(const srsue::phy_args_t& args_) -{ - // create VNF - vnf = std::unique_ptr(new srsran::srsran_basic_vnf(args_.vnf_args, stack)); - initialized = true; - return SRSRAN_SUCCESS; -} - -void vnf_phy_nr::set_earfcn(std::vector earfcns) {} - -void vnf_phy_nr::stop() -{ - if (initialized) { - vnf->stop(); - initialized = false; - } -} - -// Start GUI -void vnf_phy_nr::start_plot() {} - -void vnf_phy_nr::wait_initialize() {} - -void vnf_phy_nr::get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) {} - -int vnf_phy_nr::tx_request(const tx_request_t& request) -{ - // send Tx request over basic API - return vnf->tx_request(request); -} -bool vnf_phy_nr::set_config(const srsran::phy_cfg_nr_t& cfg) -{ - return false; -} -bool vnf_phy_nr::has_valid_sr_resource(uint32_t sr_id) -{ - return false; -} - -void vnf_phy_nr::clear_pending_grants() {} - -} // namespace srsue \ No newline at end of file diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 6e8914ff6..7b4d7cbd1 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -12,12 +12,12 @@ #include "srsue/hdr/ue.h" #include "srsran/build_info.h" +#include "srsran/common/standard_streams.h" #include "srsran/common/string_helpers.h" #include "srsran/radio/radio.h" #include "srsran/radio/radio_null.h" #include "srsran/srsran.h" #include "srsue/hdr/phy/phy.h" -#include "srsue/hdr/phy/vnf_phy_nr.h" #include "srsue/hdr/stack/ue_stack_lte.h" #include "srsue/hdr/stack/ue_stack_nr.h" #include @@ -121,7 +121,7 @@ int ue::init(const all_args_t& args_) logger.info("Initializing NR stack"); std::unique_ptr nr_stack(new srsue::ue_stack_nr()); std::unique_ptr nr_radio(new srsran::radio_null); - std::unique_ptr nr_phy(new srsue::vnf_phy_nr); + std::unique_ptr nr_phy; std::unique_ptr gw_ptr(new gw()); // Init layers @@ -130,12 +130,12 @@ int ue::init(const all_args_t& args_) return SRSRAN_ERROR; } - if (nr_phy->init(args.phy, nr_stack.get())) { + if (nr_phy->init(args.phy)) { srsran::console("Error initializing PHY.\n"); return SRSRAN_ERROR; } - if (nr_stack->init(args.stack, nr_phy.get(), gw_ptr.get())) { + if (nr_stack->init(args.stack)) { srsran::console("Error initializing stack.\n"); return SRSRAN_ERROR; } diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index ba74f1f18..6176d5aa6 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -9,7 +9,6 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) add_executable(nr_phy_test nr_phy_test.cc) target_link_libraries(nr_phy_test - srsue_phy_nr srsue_phy srsran_common srsran_phy From e0d9afc342d916d16ed59855a15ae1055b5915fe Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 13 Jul 2021 08:53:58 +0200 Subject: [PATCH 17/59] proc_ra: fix race detected with TSAN rar_received is accessed from PHY worker and Stack thread --- srsue/hdr/stack/mac/proc_ra.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/stack/mac/proc_ra.h b/srsue/hdr/stack/mac/proc_ra.h index 5d62b55bc..46ba9b4df 100644 --- a/srsue/hdr/stack/mac/proc_ra.h +++ b/srsue/hdr/stack/mac/proc_ra.h @@ -146,9 +146,9 @@ private: std::atomic transmitted_contention_id = {0}; std::atomic transmitted_crnti = {0}; - bool started_by_pdcch = false; - uint32_t rar_grant_nbytes = 0; - bool rar_received = false; + bool started_by_pdcch = false; + uint32_t rar_grant_nbytes = 0; + std::atomic rar_received = {false}; }; } // namespace srsue From c7d29f4af170b24004f522b7937d34334dae12ef Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 13 Jul 2021 08:55:24 +0200 Subject: [PATCH 18/59] ttcn3: fix potential deadlock * fix a few races detected with TSAN in SR proc of the DUT * fix deadlock caused by sync_queue_size set to 1 --- srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h | 4 ++-- srsue/src/test/ttcn3/hdr/ttcn3_syssim.h | 2 +- srsue/src/test/ttcn3/src/ttcn3_dut.cc | 2 +- srsue/src/test/ttcn3/src/ttcn3_syssim.cc | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h index 6a38708ba..e262855e8 100644 --- a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h +++ b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -119,8 +119,8 @@ private: int prach_tti_tx = -1; - int sr_tx_tti = -1; - bool sr_pending = false; + std::atomic sr_tx_tti = {-1}; + std::atomic sr_pending = {false}; std::mutex phy_mutex; diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h index 1c18195d7..667ae210d 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_syssim.h @@ -276,7 +276,7 @@ private: std::vector cells; int32_t pcell_idx = -1; - // Main mutex to protect access from syssim's main thread (epoll handlers) and calls from UE's stack thread + // Main mutex to protect access from syssim's main thread (epoll handlers) and calls from UE's stack thread std::mutex syssim_mutex; // Internal function diff --git a/srsue/src/test/ttcn3/src/ttcn3_dut.cc b/srsue/src/test/ttcn3/src/ttcn3_dut.cc index f50e2d64a..46cb23733 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_dut.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_dut.cc @@ -105,7 +105,7 @@ all_args_t parse_args(ttcn3_dut_args_t* args, int argc, char* argv[]) all_args.stack.log.gw_hex_limit = args->log_hex_level; all_args.stack.log.usim_hex_limit = args->log_hex_level; - all_args.stack.sync_queue_size = 1; + all_args.stack.sync_queue_size = MULTIQUEUE_DEFAULT_CAPACITY; return all_args; } diff --git a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc index 71c92cfca..6c689345e 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_syssim.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_syssim.cc @@ -248,8 +248,8 @@ void ttcn3_syssim::new_tti_indication(uint64_t res) // DL/UL processing if UE has selected cell dl_rnti = ue->get_dl_sched_rnti(tti); - if (SRSRAN_RNTI_ISSI(dl_rnti)) { - // deliver SIBs one after another + if (SRSRAN_RNTI_ISSI(dl_rnti) && (tti % 2 == 0)) { + // deliver SIBs one after another in every other TTI mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; dl_grant.tti = tti; dl_grant.pid = get_pid(tti); @@ -257,7 +257,7 @@ void ttcn3_syssim::new_tti_indication(uint64_t res) dl_grant.tb[0].tbs = cells[pcell_idx]->sibs[cells[pcell_idx]->sib_idx]->N_bytes; dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); ue->new_tb(dl_grant, cells[pcell_idx]->sibs[cells[pcell_idx]->sib_idx]->msg); - logger.info("Delivered SIB%d for pcell_idx=%d", cells[pcell_idx]->sib_idx, pcell_idx); + logger.info("Delivered SIB%d for pcell_idx=%d", cells[pcell_idx]->sib_idx + 1, pcell_idx); cells[pcell_idx]->sib_idx = (cells[pcell_idx]->sib_idx + 1) % cells[pcell_idx]->sibs.size(); } else if (SRSRAN_RNTI_ISRAR(dl_rnti)) { if (prach_tti != -1) { From 9d6d437ba5504b3072cc9a54440123b0c8c80cd1 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 13 Jul 2021 00:32:55 +0200 Subject: [PATCH 19/59] mac_nr,ue: don't decode RAR PDU that couldn't be decoded ignore RAR PDU when PDSCH wasn't OK --- srsue/src/stack/mac_nr/mac_nr.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index 22c023906..07191e613 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -297,7 +297,9 @@ void mac_nr::tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, t write_pcap(cc_idx, grant, result); if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { - proc_ra.handle_rar_pdu(result); + if (result.ack && result.payload != nullptr) { + proc_ra.handle_rar_pdu(result); + } } else { // Assert HARQ entity if (dl_harq.at(cc_idx) == nullptr) { From 59ca11db6864be295af9bc474cc0f504fb8937a7 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 11 Jul 2021 19:36:31 +0200 Subject: [PATCH 20/59] Added missing target_link_libs --- srsenb/src/stack/upper/CMakeLists.txt | 1 + srsue/src/stack/upper/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/srsenb/src/stack/upper/CMakeLists.txt b/srsenb/src/stack/upper/CMakeLists.txt index f86393693..30e22062c 100644 --- a/srsenb/src/stack/upper/CMakeLists.txt +++ b/srsenb/src/stack/upper/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES gtpu.cc pdcp.cc rlc.cc) add_library(srsenb_upper STATIC ${SOURCES}) +target_link_libraries(srsenb_upper srsran_asn1 srsran_gtpu) set(SOURCES pdcp_nr.cc rlc_nr.cc sdap.cc) add_library(srsgnb_upper STATIC ${SOURCES}) diff --git a/srsue/src/stack/upper/CMakeLists.txt b/srsue/src/stack/upper/CMakeLists.txt index 426c38a73..3038c610c 100644 --- a/srsue/src/stack/upper/CMakeLists.txt +++ b/srsue/src/stack/upper/CMakeLists.txt @@ -15,7 +15,7 @@ if(HAVE_PCSC) endif(HAVE_PCSC) add_library(srsue_upper STATIC ${SOURCES}) -target_link_libraries(srsue_upper ${ATOMIC_LIBS}) +target_link_libraries(srsue_upper ${ATOMIC_LIBS} srsran_asn1) if(HAVE_PCSC) target_link_libraries(srsue_upper ${PCSCLITE_LIBRARY}) From 709b706d07491baa94097c8ca17456abeb7b20a4 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 9 Jul 2021 09:23:38 +0200 Subject: [PATCH 21/59] Fix 5G NAS extended protocol discriminator --- lib/include/srsran/asn1/nas_5g_msg.h | 176 ++++++++++++++++++++------- 1 file changed, 132 insertions(+), 44 deletions(-) diff --git a/lib/include/srsran/asn1/nas_5g_msg.h b/lib/include/srsran/asn1/nas_5g_msg.h index cdf7225fe..5edb3f20e 100644 --- a/lib/include/srsran/asn1/nas_5g_msg.h +++ b/lib/include/srsran/asn1/nas_5g_msg.h @@ -2118,265 +2118,353 @@ public: registration_request_t& set_registration_request() { set(msg_types::options::registration_request); - msg_container = srslog::detail::any{registration_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{registration_request_t()}; return *srslog::detail::any_cast(&msg_container); } registration_accept_t& set_registration_accept() { set(msg_types::options::registration_accept); - msg_container = srslog::detail::any{registration_accept_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{registration_accept_t()}; return *srslog::detail::any_cast(&msg_container); } registration_complete_t& set_registration_complete() { set(msg_types::options::registration_complete); - msg_container = srslog::detail::any{registration_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{registration_complete_t()}; return *srslog::detail::any_cast(&msg_container); } registration_reject_t& set_registration_reject() { set(msg_types::options::registration_reject); - msg_container = srslog::detail::any{registration_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{registration_reject_t()}; return *srslog::detail::any_cast(&msg_container); } deregistration_request_ue_originating_t& set_deregistration_request_ue_originating() { set(msg_types::options::deregistration_request_ue_originating); - msg_container = srslog::detail::any{deregistration_request_ue_originating_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{deregistration_request_ue_originating_t()}; return *srslog::detail::any_cast(&msg_container); } deregistration_accept_ue_originating_t& set_deregistration_accept_ue_originating() { set(msg_types::options::deregistration_accept_ue_originating); - msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()}; return *srslog::detail::any_cast(&msg_container); } deregistration_request_ue_terminated_t& set_deregistration_request_ue_terminated() { set(msg_types::options::deregistration_request_ue_terminated); - msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()}; return *srslog::detail::any_cast(&msg_container); } deregistration_accept_ue_terminated_t& set_deregistration_accept_ue_terminated() { set(msg_types::options::deregistration_accept_ue_terminated); - msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()}; return *srslog::detail::any_cast(&msg_container); } service_request_t& set_service_request() { set(msg_types::options::service_request); - msg_container = srslog::detail::any{service_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{service_request_t()}; return *srslog::detail::any_cast(&msg_container); } service_reject_t& set_service_reject() { set(msg_types::options::service_reject); - msg_container = srslog::detail::any{service_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{service_reject_t()}; return *srslog::detail::any_cast(&msg_container); } service_accept_t& set_service_accept() { set(msg_types::options::service_accept); - msg_container = srslog::detail::any{service_accept_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{service_accept_t()}; return *srslog::detail::any_cast(&msg_container); } configuration_update_command_t& set_configuration_update_command() { set(msg_types::options::configuration_update_command); - msg_container = srslog::detail::any{configuration_update_command_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{configuration_update_command_t()}; return *srslog::detail::any_cast(&msg_container); } configuration_update_complete_t& set_configuration_update_complete() { set(msg_types::options::configuration_update_complete); - msg_container = srslog::detail::any{configuration_update_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{configuration_update_complete_t()}; return *srslog::detail::any_cast(&msg_container); } authentication_request_t& set_authentication_request() { set(msg_types::options::authentication_request); - msg_container = srslog::detail::any{authentication_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{authentication_request_t()}; return *srslog::detail::any_cast(&msg_container); } authentication_response_t& set_authentication_response() { set(msg_types::options::authentication_response); - msg_container = srslog::detail::any{authentication_response_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{authentication_response_t()}; return *srslog::detail::any_cast(&msg_container); } authentication_reject_t& set_authentication_reject() { set(msg_types::options::authentication_reject); - msg_container = srslog::detail::any{authentication_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{authentication_reject_t()}; return *srslog::detail::any_cast(&msg_container); } authentication_failure_t& set_authentication_failure() { set(msg_types::options::authentication_failure); - msg_container = srslog::detail::any{authentication_failure_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{authentication_failure_t()}; return *srslog::detail::any_cast(&msg_container); } authentication_result_t& set_authentication_result() { set(msg_types::options::authentication_result); - msg_container = srslog::detail::any{authentication_result_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{authentication_result_t()}; return *srslog::detail::any_cast(&msg_container); } identity_request_t& set_identity_request() { set(msg_types::options::identity_request); - msg_container = srslog::detail::any{identity_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{identity_request_t()}; return *srslog::detail::any_cast(&msg_container); } identity_response_t& set_identity_response() { set(msg_types::options::identity_response); - msg_container = srslog::detail::any{identity_response_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{identity_response_t()}; return *srslog::detail::any_cast(&msg_container); } security_mode_command_t& set_security_mode_command() { set(msg_types::options::security_mode_command); - msg_container = srslog::detail::any{security_mode_command_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{security_mode_command_t()}; return *srslog::detail::any_cast(&msg_container); } security_mode_complete_t& set_security_mode_complete() { set(msg_types::options::security_mode_complete); - msg_container = srslog::detail::any{security_mode_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{security_mode_complete_t()}; return *srslog::detail::any_cast(&msg_container); } security_mode_reject_t& set_security_mode_reject() { set(msg_types::options::security_mode_reject); - msg_container = srslog::detail::any{security_mode_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{security_mode_reject_t()}; return *srslog::detail::any_cast(&msg_container); } status_5gmm_t& set_status_5gmm() { set(msg_types::options::status_5gmm); - msg_container = srslog::detail::any{status_5gmm_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{status_5gmm_t()}; return *srslog::detail::any_cast(&msg_container); } notification_t& set_notification() { set(msg_types::options::notification); - msg_container = srslog::detail::any{notification_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{notification_t()}; return *srslog::detail::any_cast(&msg_container); } notification_response_t& set_notification_response() { set(msg_types::options::notification_response); - msg_container = srslog::detail::any{notification_response_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{notification_response_t()}; return *srslog::detail::any_cast(&msg_container); } ul_nas_transport_t& set_ul_nas_transport() { set(msg_types::options::ul_nas_transport); - msg_container = srslog::detail::any{ul_nas_transport_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{ul_nas_transport_t()}; return *srslog::detail::any_cast(&msg_container); } dl_nas_transport_t& set_dl_nas_transport() { set(msg_types::options::dl_nas_transport); - msg_container = srslog::detail::any{dl_nas_transport_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm; + msg_container = srslog::detail::any{dl_nas_transport_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_establishment_request_t& set_pdu_session_establishment_request() { set(msg_types::options::pdu_session_establishment_request); - msg_container = srslog::detail::any{pdu_session_establishment_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_establishment_request_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_establishment_accept_t& set_pdu_session_establishment_accept() { set(msg_types::options::pdu_session_establishment_accept); - msg_container = srslog::detail::any{pdu_session_establishment_accept_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_establishment_accept_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_establishment_reject_t& set_pdu_session_establishment_reject() { set(msg_types::options::pdu_session_establishment_reject); - msg_container = srslog::detail::any{pdu_session_establishment_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_establishment_reject_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_authentication_command_t& set_pdu_session_authentication_command() { set(msg_types::options::pdu_session_authentication_command); - msg_container = srslog::detail::any{pdu_session_authentication_command_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_authentication_command_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_authentication_complete_t& set_pdu_session_authentication_complete() { set(msg_types::options::pdu_session_authentication_complete); - msg_container = srslog::detail::any{pdu_session_authentication_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_authentication_complete_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_authentication_result_t& set_pdu_session_authentication_result() { set(msg_types::options::pdu_session_authentication_result); - msg_container = srslog::detail::any{pdu_session_authentication_result_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_authentication_result_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_modification_request_t& set_pdu_session_modification_request() { set(msg_types::options::pdu_session_modification_request); - msg_container = srslog::detail::any{pdu_session_modification_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_modification_request_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_modification_reject_t& set_pdu_session_modification_reject() { set(msg_types::options::pdu_session_modification_reject); - msg_container = srslog::detail::any{pdu_session_modification_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_modification_reject_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_modification_command_t& set_pdu_session_modification_command() { set(msg_types::options::pdu_session_modification_command); - msg_container = srslog::detail::any{pdu_session_modification_command_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_modification_command_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_modification_complete_t& set_pdu_session_modification_complete() { set(msg_types::options::pdu_session_modification_complete); - msg_container = srslog::detail::any{pdu_session_modification_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_modification_complete_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_modification_command_reject_t& set_pdu_session_modification_command_reject() { set(msg_types::options::pdu_session_modification_command_reject); - msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_release_request_t& set_pdu_session_release_request() { set(msg_types::options::pdu_session_release_request); - msg_container = srslog::detail::any{pdu_session_release_request_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_release_request_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_release_reject_t& set_pdu_session_release_reject() { set(msg_types::options::pdu_session_release_reject); - msg_container = srslog::detail::any{pdu_session_release_reject_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_release_reject_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_release_command_t& set_pdu_session_release_command() { set(msg_types::options::pdu_session_release_command); - msg_container = srslog::detail::any{pdu_session_release_command_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_release_command_t()}; return *srslog::detail::any_cast(&msg_container); } pdu_session_release_complete_t& set_pdu_session_release_complete() { set(msg_types::options::pdu_session_release_complete); - msg_container = srslog::detail::any{pdu_session_release_complete_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{pdu_session_release_complete_t()}; return *srslog::detail::any_cast(&msg_container); } status_5gsm_t& set_status_5gsm() { set(msg_types::options::status_5gsm); - msg_container = srslog::detail::any{status_5gsm_t()}; + hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm; + msg_container = srslog::detail::any{status_5gsm_t()}; return *srslog::detail::any_cast(&msg_container); } From e0b09f13014bf49db19770068fe45b49e6527c0d Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Tue, 13 Jul 2021 09:48:08 +0200 Subject: [PATCH 22/59] Fixed coverity findings --- lib/src/asn1/nas_5g_ies.cc | 142 ++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/lib/src/asn1/nas_5g_ies.cc b/lib/src/asn1/nas_5g_ies.cc index b90265f61..9e5975dee 100644 --- a/lib/src/asn1/nas_5g_ies.cc +++ b/lib/src/asn1/nas_5g_ies.cc @@ -432,7 +432,7 @@ SRSASN_CODE capability_5gmm_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(cag, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 13) { asn1::log_error("Encoding Failed (5GMM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes", @@ -532,7 +532,7 @@ SRSASN_CODE ue_security_capability_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(eia7_supported, 1)); } bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 8) { asn1::log_error( @@ -608,7 +608,7 @@ SRSASN_CODE nssai_t::pack(asn1::bit_ref& bref) } bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 144) { asn1::log_error("Encoding Failed (NSSAI): Packed length (%d) is not in range of min: 2 and max 144 bytes", length); @@ -733,7 +733,7 @@ SRSASN_CODE s1_ue_network_capability_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(racs_supported, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 13) { asn1::log_error( @@ -878,7 +878,7 @@ SRSASN_CODE uplink_data_status_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(psi_8, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 32) { asn1::log_error( @@ -948,7 +948,7 @@ SRSASN_CODE pdu_session_status_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(psi_8, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 32) { asn1::log_error( @@ -1028,7 +1028,7 @@ SRSASN_CODE ue_status_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(s1_mode_reg, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (UE status): Packed length (%d) does not equal expected length 1", length); @@ -1080,7 +1080,7 @@ SRSASN_CODE allowed_pdu_session_status_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(psi_8, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 32) { asn1::log_error( @@ -1138,7 +1138,7 @@ SRSASN_CODE ue_usage_setting_t::pack(asn1::bit_ref& bref) HANDLE_CODE(ue_usage_setting.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (UE usage setting): Packed length (%d) does not equal expected length 1", length); @@ -1176,7 +1176,7 @@ SRSASN_CODE drx_parameters_5gs_t::pack(asn1::bit_ref& bref) HANDLE_CODE(drx_value.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (5GS DRX parameters): Packed length (%d) does not equal expected length 1", @@ -1212,7 +1212,7 @@ SRSASN_CODE eps_nas_message_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(eps_nas_message_container.data(), eps_nas_message_container.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); HANDLE_CODE(bref_length.pack(length, 16)); return SRSASN_SUCCESS; @@ -1241,7 +1241,7 @@ SRSASN_CODE ladn_indication_t::pack(asn1::bit_ref& bref) } bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MIN 0 not check because auf uint underflow if (length > 808) { @@ -1297,7 +1297,7 @@ SRSASN_CODE payload_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(payload_container_contents.data(), payload_container_contents.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 1) { @@ -1361,7 +1361,7 @@ SRSASN_CODE update_type_5gs_t::pack(asn1::bit_ref& bref) HANDLE_CODE(sms_requested.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -1391,7 +1391,7 @@ SRSASN_CODE mobile_station_classmark_2_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 3) { asn1::log_error("Encoding Failed (Mobile station classmark 2): Packed length (%d) does not equal expected length 3", @@ -1429,7 +1429,7 @@ SRSASN_CODE supported_codec_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 3) { asn1::log_error("Encoding Failed (Supported codec list): Packed length (%d) is not in range of min: 3 bytes", @@ -1465,7 +1465,7 @@ SRSASN_CODE message_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); if (length < 1 || length > 65532) { asn1::log_error( @@ -1518,7 +1518,7 @@ SRSASN_CODE eps_bearer_context_status_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(ebi_8, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 2) { asn1::log_error("Encoding Failed (EPS bearer context status): Packed length (%d) does not equal expected length 2", @@ -1570,7 +1570,7 @@ SRSASN_CODE extended_drx_parameters_t::pack(asn1::bit_ref& bref) HANDLE_CODE(e_drx_value.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (Extended DRX parameters): Packed length (%d) does not equal expected length 1", @@ -1607,7 +1607,7 @@ SRSASN_CODE gprs_timer_3_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(timer_value, 5)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (GPRS timer 3): Packed length (%d) does not equal expected length 1", length); @@ -1641,7 +1641,7 @@ SRSASN_CODE ue_radio_capability_id_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(ue_radio_capability_id.data(), ue_radio_capability_id.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -1668,7 +1668,7 @@ SRSASN_CODE mapped_nssai_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 40) { asn1::log_error("Encoding Failed (Mapped NSSAI): Packed length (%d) is not in range of min: 2 and max 40 bytes", @@ -1707,7 +1707,7 @@ SRSASN_CODE additional_information_requested_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(cipher_key, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -1734,7 +1734,7 @@ SRSASN_CODE wus_assistance_information_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1) { asn1::log_error("Encoding Failed (WUS assistance information): Packed length (%d) is not in range of min: 1 bytes", @@ -1794,7 +1794,7 @@ SRSASN_CODE nb_n1_mode_drx_parameters_t::pack(asn1::bit_ref& bref) HANDLE_CODE(nb_n1_mode_drx_value.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (NB-N1 mode DRX parameters): Packed length (%d) does not equal expected length 1", @@ -1837,7 +1837,7 @@ SRSASN_CODE registration_result_5gs_t::pack(asn1::bit_ref& bref) HANDLE_CODE(registration_result.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (5GS registration result): Packed length (%d) does not equal expected length 1", @@ -1877,7 +1877,7 @@ SRSASN_CODE plmn_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -1904,7 +1904,7 @@ SRSASN_CODE tracking_area_identity_list_5gs_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 7) { asn1::log_error( @@ -1943,7 +1943,7 @@ SRSASN_CODE rejected_nssai_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -1970,7 +1970,7 @@ SRSASN_CODE network_feature_support_5gs_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 3) { asn1::log_error( @@ -2024,7 +2024,7 @@ SRSASN_CODE pdu_session_reactivation_result_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(psi_8, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 32) { asn1::log_error("Encoding Failed (PDU session reactivation result): Packed length (%d) is not in range of min: 2 " @@ -2083,7 +2083,7 @@ SRSASN_CODE pdu_session_reactivation_result_error_cause_t::pack(asn1::bit_ref& b // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); if (length < 2 || length > 512) { asn1::log_error("Encoding Failed (PDU session reactivation result error cause): Packed length (%d) is not in range " @@ -2123,7 +2123,7 @@ SRSASN_CODE ladn_information_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MIN 0 not check because auf uint underflow if (length > 1712) { @@ -2161,7 +2161,7 @@ SRSASN_CODE service_area_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -2188,7 +2188,7 @@ SRSASN_CODE gprs_timer_2_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(timer_value, 8)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (GPRS timer 2): Packed length (%d) does not equal expected length 1", length); @@ -2222,7 +2222,7 @@ SRSASN_CODE emergency_number_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 3 || length > 48) { asn1::log_error( @@ -2261,7 +2261,7 @@ SRSASN_CODE extended_emergency_number_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 4) { @@ -2301,7 +2301,7 @@ SRSASN_CODE sor_transparent_container_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); if (length < 17) { asn1::log_error("Encoding Failed (SOR transparent container): Packed length (%d) is not in range of min: 17 bytes", @@ -2338,7 +2338,7 @@ SRSASN_CODE eap_message_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(eap_message.data(), eap_message.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); if (length < 4 || length > 1500) { asn1::log_error("Encoding Failed (EAP message): Packed length (%d) is not in range of min: 4 and max 1500 bytes", @@ -2394,7 +2394,7 @@ SRSASN_CODE operator_defined_access_category_definitions_t::pack(asn1::bit_ref& // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); HANDLE_CODE(bref_length.pack(length, 16)); return SRSASN_SUCCESS; @@ -2461,7 +2461,7 @@ SRSASN_CODE ciphering_key_data_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); if (length < 31 || length > 2672) { asn1::log_error( @@ -2500,7 +2500,7 @@ SRSASN_CODE cag_information_list_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); HANDLE_CODE(bref_length.pack(length, 16)); return SRSASN_SUCCESS; @@ -2528,7 +2528,7 @@ SRSASN_CODE truncated_5g_s_tmsi_configuration_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(truncated_amf__pointer_value, 4)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error( @@ -2656,7 +2656,7 @@ SRSASN_CODE network_name_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); HANDLE_CODE(bref_length.pack(length, 8)); return SRSASN_SUCCESS; @@ -2725,7 +2725,7 @@ SRSASN_CODE daylight_saving_time_t::pack(asn1::bit_ref& bref) HANDLE_CODE(value.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (Daylight saving time): Packed length (%d) does not equal expected length 1", @@ -2799,7 +2799,7 @@ SRSASN_CODE abba_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(abba_contents.data(), abba_contents.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2) { asn1::log_error("Encoding Failed (ABBA): Packed length (%d) is not in range of min: 2 bytes", length); @@ -2849,7 +2849,7 @@ SRSASN_CODE authentication_parameter_autn_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(autn.data(), autn.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 16) { asn1::log_error( @@ -2886,7 +2886,7 @@ SRSASN_CODE authentication_response_parameter_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(res.data(), res.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 16) { asn1::log_error( @@ -2923,7 +2923,7 @@ SRSASN_CODE authentication_failure_parameter_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(auth_failure.data(), auth_failure.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 14) { asn1::log_error( @@ -3049,7 +3049,7 @@ SRSASN_CODE additional_5g_security_information_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(hdp, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error( @@ -3132,7 +3132,7 @@ SRSASN_CODE s1_ue_security_capability_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(gea7, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 2 || length > 5) { asn1::log_error( @@ -3296,7 +3296,7 @@ SRSASN_CODE s_nssai_t::pack(asn1::bit_ref& bref) } bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 8) { asn1::log_error("Encoding Failed (S-NSSAI): Packed length (%d) is not in range of min: 1 and max 8 bytes", length); @@ -3345,7 +3345,7 @@ SRSASN_CODE dnn_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(dnn_value.data(), dnn_value.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 100) { asn1::log_error("Encoding Failed (DNN): Packed length (%d) is not in range of min: 1 and max 100 bytes", length); @@ -3379,7 +3379,7 @@ SRSASN_CODE additional_information_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(additional_information_value.data(), additional_information_value.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1) { asn1::log_error("Encoding Failed (Additional information): Packed length (%d) is not in range of min: 1 bytes", @@ -3509,7 +3509,7 @@ SRSASN_CODE capability_5gsm_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 13) { asn1::log_error("Encoding Failed (5GSM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes", @@ -3587,7 +3587,7 @@ SRSASN_CODE sm_pdu_dn_request_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(dn_specific_identity.data(), dn_specific_identity.size())); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 253) { asn1::log_error( @@ -3626,7 +3626,7 @@ SRSASN_CODE extended_protocol_configuration_options_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 1) { @@ -3668,7 +3668,7 @@ SRSASN_CODE ip_header_compression_configuration_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); // MAX 255 not check because auf uint overflow if (length < 3) { @@ -3709,7 +3709,7 @@ SRSASN_CODE ds_tt__ethernet_port_mac_address_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(ds_tt__ethernet_port_mac_address_contents.data(), 6)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 6) { asn1::log_error( @@ -3746,7 +3746,7 @@ SRSASN_CODE ue_ds_tt_residence_time_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(ue_ds_tt_residence_time_contents.data(), 8)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 8) { asn1::log_error("Encoding Failed (UE-DS-TT residence time): Packed length (%d) does not equal expected length 8", @@ -3781,7 +3781,7 @@ SRSASN_CODE port_management_information_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE( bref.pack_bytes(port_management_information_container.data(), port_management_information_container.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 1) { @@ -3823,7 +3823,7 @@ SRSASN_CODE ethernet_header_compression_configuration_t::pack(asn1::bit_ref& bre HANDLE_CODE(cid__length.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (Ethernet header compression configuration): Packed length (%d) does not equal " @@ -3879,7 +3879,7 @@ SRSASN_CODE pdu_address_t::pack(asn1::bit_ref& bref) } bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 5 || length > 29) { asn1::log_error("Encoding Failed (PDU address): Packed length (%d) is not in range of min: 5 and max 29 bytes", @@ -3938,7 +3938,7 @@ SRSASN_CODE qo_s_rules_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.advance_bits(16)); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 4) { @@ -3977,7 +3977,7 @@ SRSASN_CODE session_ambr_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(session_ambr_for_uplink, 16)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 6) { asn1::log_error("Encoding Failed (Session-AMBR): Packed length (%d) does not equal expected length 6", length); @@ -4068,7 +4068,7 @@ SRSASN_CODE mapped_eps_bearer_contexts_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 4) { @@ -4108,7 +4108,7 @@ SRSASN_CODE qo_s_flow_descriptions_t::pack(asn1::bit_ref& bref) // TODO proper packing bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MAX 65535 not check because auf uint overflow if (length < 3) { @@ -4149,7 +4149,7 @@ SRSASN_CODE network_feature_support_5gsm_t::pack(asn1::bit_ref& bref) HANDLE_CODE(ept_s1.pack(bref)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length < 1 || length > 13) { asn1::log_error( @@ -4192,7 +4192,7 @@ SRSASN_CODE serving_plmn_rate_control_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(serving_plmn_rate_control_value, 16)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 2) { asn1::log_error("Encoding Failed (Serving PLMN rate control): Packed length (%d) does not equal expected length 2", @@ -4227,7 +4227,7 @@ SRSASN_CODE atsss_container_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size())); bref.align_bytes_zero(); - uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2); + uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2); // MIN 0 not check because auf uint underflow // MAX 65535 not check because auf uint overflow @@ -4328,7 +4328,7 @@ SRSASN_CODE re_attempt_indicator_t::pack(asn1::bit_ref& bref) HANDLE_CODE(bref.pack(ratc, 1)); bref.align_bytes_zero(); - uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1); + uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1); if (length != 1) { asn1::log_error("Encoding Failed (Re-attempt indicator): Packed length (%d) does not equal expected length 1", From 47747e3148737c6ae7f740c6a7c6008f49a508a1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 7 Jul 2021 11:16:59 +0200 Subject: [PATCH 23/59] SRSENB: RRC measurement report for NR are appended --- srsenb/src/stack/rrc/rrc_endc.cc | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index 7c6a1fc49..d8a298a4f 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -47,18 +47,18 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn meas_cfg_s& meas_cfg = conn_recfg->meas_cfg; meas_cfg.meas_obj_to_add_mod_list_present = true; - meas_cfg.meas_obj_to_add_mod_list.resize(2); - auto& meas_obj = meas_cfg.meas_obj_to_add_mod_list[0]; - meas_obj.meas_obj_id = 1; + meas_obj_to_add_mod_s meas_obj = {}; + meas_obj.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1; meas_obj.meas_obj.set_meas_obj_eutra(); meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300; meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50; meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false; meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01); + meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj); - auto& meas_obj2 = meas_cfg.meas_obj_to_add_mod_list[1]; - meas_obj2.meas_obj_id = 2; + meas_obj_to_add_mod_s meas_obj2 = {}; + meas_obj2.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1; meas_obj2.meas_obj.set_meas_obj_nr_r15(); meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176; meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15(); @@ -69,13 +69,13 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn meas_obj2.meas_obj.meas_obj_nr_r15().ext = true; meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true); meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78; + meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj2); // report config meas_cfg.report_cfg_to_add_mod_list_present = true; - meas_cfg.report_cfg_to_add_mod_list.resize(1); - auto& report_cfg = meas_cfg.report_cfg_to_add_mod_list[0]; + report_cfg_to_add_mod_s report_cfg = {}; - report_cfg.report_cfg_id = 1; + report_cfg.report_cfg_id = meas_cfg.report_cfg_to_add_mod_list.size() + 1; report_cfg.report_cfg.set_report_cfg_inter_rat(); report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.set_event(); report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.set_event_b1_nr_r15(); @@ -100,14 +100,15 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrp = true; report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrq = true; report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_sinr = true; + meas_cfg.report_cfg_to_add_mod_list.push_back(report_cfg); // measIdToAddModList meas_cfg.meas_id_to_add_mod_list_present = true; - meas_cfg.meas_id_to_add_mod_list.resize(1); - auto& meas_id = meas_cfg.meas_id_to_add_mod_list[0]; - meas_id.meas_id = 1; - meas_id.meas_obj_id = 2; - meas_id.report_cfg_id = 1; + meas_id_to_add_mod_s meas_id = {}; + meas_id.meas_id = meas_obj.meas_obj_id; + meas_id.meas_obj_id = meas_obj2.meas_obj_id; + meas_id.report_cfg_id = report_cfg.report_cfg_id; + meas_cfg.meas_id_to_add_mod_list.push_back(meas_id); // quantityConfig meas_cfg.quant_cfg_present = true; From 7fa85ab336b9f2c18cec44777b37921edbdd6405 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 7 Jul 2021 16:36:36 +0200 Subject: [PATCH 24/59] Added nas test common file --- srsue/hdr/stack/upper/test/nas_test_common.h | 183 ++++++++++++ srsue/src/stack/upper/test/nas_test.cc | 298 ++++--------------- 2 files changed, 249 insertions(+), 232 deletions(-) create mode 100644 srsue/hdr/stack/upper/test/nas_test_common.h diff --git a/srsue/hdr/stack/upper/test/nas_test_common.h b/srsue/hdr/stack/upper/test/nas_test_common.h new file mode 100644 index 000000000..1af31d3c7 --- /dev/null +++ b/srsue/hdr/stack/upper/test/nas_test_common.h @@ -0,0 +1,183 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_NAS_TEST_COMMON +#define SRSUE_NAS_TEST_COMMON + +#include "srsran/common/bcd_helpers.h" +#include "srsran/common/test_common.h" +#include "srsran/common/tsan_options.h" +#include "srsran/interfaces/ue_pdcp_interfaces.h" +#include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/srslog/srslog.h" +#include "srsran/test/ue_test_interfaces.h" +#include "srsue/hdr/stack/upper/gw.h" +#include "srsue/hdr/stack/upper/nas.h" +#include "srsue/hdr/stack/upper/usim.h" +#include "srsue/hdr/stack/upper/usim_base.h" + +#define LCID 1 + +uint8_t auth_request_pdu[] = {0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0xe6, 0xa4, 0xce, 0xd9, + 0x86, 0xfb, 0xe5, 0xce, 0x9b, 0x62, 0x5e, 0x10, 0x67, 0x57, 0xb3, 0xc2, + 0xb9, 0x70, 0x90, 0x01, 0x0c, 0x72, 0x8a, 0x67, 0x57, 0x92, 0x52, 0xb8}; + +uint8_t sec_mode_command_pdu[] = {0x37, 0x4e, 0xfd, 0x57, 0x11, 0x00, 0x07, 0x5d, 0x02, 0x01, 0x02, 0xf0, 0x70, 0xc1}; + +uint8_t attach_accept_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0x01, 0x3e, 0x06, 0x00, 0x00, + 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, + 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, + 0x31, 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, + 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, 0x80, 0x50, 0x0b, 0xf6, 0x00, + 0xf1, 0x10, 0x80, 0x01, 0x01, 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00}; + +uint8_t esm_info_req_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd9}; + +uint8_t activate_dedicated_eps_bearer_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0xc5, 0x05, + 0x01, 0x01, 0x07, 0x21, 0x31, 0x00, 0x03, 0x40, 0x08, 0xae, + 0x5d, 0x02, 0x00, 0xc2, 0x81, 0x34, 0x01, 0x4d}; + +uint8_t deactivate_eps_bearer_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0xcd, 0x24}; + +uint16 mcc = 61441; +uint16 mnc = 65281; + +using namespace srsue; + +namespace srsran { + +// fake classes +class pdcp_dummy : public rrc_interface_pdcp, public pdcp_interface_stack +{ +public: + void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) override {} + void write_pdu_bcch_bch(unique_byte_buffer_t pdu) override {} + void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) override {} + void write_pdu_pcch(unique_byte_buffer_t pdu) override {} + void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override {} + const char* get_rb_name(uint32_t lcid) override { return "lcid"; } + void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override {} + bool is_eps_bearer_id_enabled(uint32_t eps_bearer_id) { return false; } + void notify_pdcp_integrity_error(uint32_t lcid) override {} + bool is_lcid_enabled(uint32_t lcid) override { return false; } +}; + +class rrc_dummy : public rrc_interface_nas +{ +public: + rrc_dummy() : last_sdu_len(0) + { + plmns[0].plmn_id.from_number(mcc, mnc); + plmns[0].tac = 0xffff; + } + void init(nas* nas_) { nas_ptr = nas_; } + void write_sdu(unique_byte_buffer_t sdu) + { + last_sdu_len = sdu->N_bytes; + // printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + // srsran_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + } + const char* get_rb_name(uint32_t lcid) { return "lcid"; } + uint32_t get_last_sdu_len() { return last_sdu_len; } + void reset() { last_sdu_len = 0; } + + bool plmn_search() + { + nas_ptr->plmn_search_completed(plmns, 1); + return true; + } + void plmn_select(srsran::plmn_id_t plmn_id){}; + void set_ue_identity(srsran::s_tmsi_t s_tmsi) {} + bool connection_request(srsran::establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) + { + printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + last_sdu_len = sdu->N_bytes; + srsran_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + is_connected_flag = true; + nas_ptr->connection_request_completed(true); + return true; + } + bool is_connected() { return is_connected_flag; } + + uint16_t get_mcc() { return mcc; } + uint16_t get_mnc() { return mnc; } + void enable_capabilities() {} + uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) { return 0; } + void paging_completed(bool outcome) {} + bool has_nr_dc() { return false; } + +private: + nas* nas_ptr; + uint32_t last_sdu_len; + nas_interface_rrc::found_plmn_t plmns[nas_interface_rrc::MAX_FOUND_PLMNS]; + bool is_connected_flag = false; +}; + +template +class test_stack_dummy : public srsue::stack_test_dummy, public stack_interface_gw, public thread +{ +public: + test_stack_dummy(pdcp_interface_stack* pdcp_) : pdcp(pdcp_), thread("DUMMY STACK") {} + void init(T* nas_) + { + nas = nas_; + start(-1); + } + bool switch_on() { nas->switch_on(); return true; } + void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); } + bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; } + + bool is_registered() { return true; } + + bool start_service_request() { return true; } + + void run_thread() + { + running = true; + while (running) { + task_sched.tic(); + task_sched.run_pending_tasks(); + nas->run_tti(); + } + } + void stop() + { + while (not running) { + usleep(1000); + } + running = false; + wait_thread_finish(); + } + pdcp_interface_stack* pdcp = nullptr; + T* nas = nullptr; + std::atomic running = {false}; +}; + +class gw_dummy : public gw_interface_nas, public gw_interface_pdcp +{ + int setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) + { + return SRSRAN_SUCCESS; + } + int deactivate_eps_bearer(const uint32_t eps_bearer_id) { return SRSRAN_SUCCESS; } + int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) + { + return SRSRAN_SUCCESS; + } + void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) {} + void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} + void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms = 0) {} +}; + +} // namespace srsran + +#endif // SRSUE_NAS_TEST_COMMON \ No newline at end of file diff --git a/srsue/src/stack/upper/test/nas_test.cc b/srsue/src/stack/upper/test/nas_test.cc index 11f52a7a6..825d29ee4 100644 --- a/srsue/src/stack/upper/test/nas_test.cc +++ b/srsue/src/stack/upper/test/nas_test.cc @@ -18,10 +18,12 @@ #include "srsran/test/ue_test_interfaces.h" #include "srsue/hdr/stack/upper/gw.h" #include "srsue/hdr/stack/upper/nas.h" +#include "srsue/hdr/stack/upper/test/nas_test_common.h" #include "srsue/hdr/stack/upper/usim.h" #include "srsue/hdr/stack/upper/usim_base.h" using namespace srsue; +using namespace srsran; static_assert(alignof(LIBLTE_BYTE_MSG_STRUCT) == alignof(byte_buffer_t), "liblte buffer and byte buffer members misaligned"); @@ -32,164 +34,74 @@ static_assert(offsetof(LIBLTE_BYTE_MSG_STRUCT, header) == offsetof(byte_buffer_t static_assert(sizeof(LIBLTE_BYTE_MSG_STRUCT) <= offsetof(byte_buffer_t, msg), "liblte buffer and byte buffer members misaligned"); -#define LCID 1 - -uint8_t auth_request_pdu[] = {0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0xe6, 0xa4, 0xce, 0xd9, - 0x86, 0xfb, 0xe5, 0xce, 0x9b, 0x62, 0x5e, 0x10, 0x67, 0x57, 0xb3, 0xc2, - 0xb9, 0x70, 0x90, 0x01, 0x0c, 0x72, 0x8a, 0x67, 0x57, 0x92, 0x52, 0xb8}; - -uint8_t sec_mode_command_pdu[] = {0x37, 0x4e, 0xfd, 0x57, 0x11, 0x00, 0x07, 0x5d, 0x02, 0x01, 0x02, 0xf0, 0x70, 0xc1}; - -uint8_t attach_accept_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0x01, 0x3e, 0x06, 0x00, 0x00, - 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, - 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, - 0x31, 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, - 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, 0x80, 0x50, 0x0b, 0xf6, 0x00, - 0xf1, 0x10, 0x80, 0x01, 0x01, 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00}; - -uint8_t esm_info_req_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd9}; - -uint8_t activate_dedicated_eps_bearer_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0xc5, 0x05, - 0x01, 0x01, 0x07, 0x21, 0x31, 0x00, 0x03, 0x40, 0x08, 0xae, - 0x5d, 0x02, 0x00, 0xc2, 0x81, 0x34, 0x01, 0x4d}; - -uint8_t deactivate_eps_bearer_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0xcd, 0x24}; - -uint16 mcc = 61441; -uint16 mnc = 65281; - -using namespace srsran; - -namespace srsran { - -// fake classes -class pdcp_dummy : public rrc_interface_pdcp, public pdcp_interface_stack +int mme_attach_request_test() { -public: - void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) override {} - void write_pdu_bcch_bch(unique_byte_buffer_t pdu) override {} - void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) override {} - void write_pdu_pcch(unique_byte_buffer_t pdu) override {} - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override {} - const char* get_rb_name(uint32_t lcid) override { return "lcid"; } - void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override {} - bool is_eps_bearer_id_enabled(uint32_t eps_bearer_id) { return false; } - void notify_pdcp_integrity_error(uint32_t lcid) override {} - bool is_lcid_enabled(uint32_t lcid) override { return false; } -}; + int ret = SRSRAN_ERROR; + + rrc_dummy rrc_dummy; + pdcp_dummy pdcp_dummy; + + srsue::usim usim(srslog::fetch_basic_logger("USIM")); + usim_args_t args; + args.mode = "soft"; + args.algo = "xor"; + args.imei = "353490069873319"; + args.imsi = "001010123456789"; + args.k = "00112233445566778899aabbccddeeff"; + args.op = "63BFA50EE6523365FF14C1F45F88737D"; + usim.init(&args); -class rrc_dummy : public rrc_interface_nas -{ -public: - rrc_dummy() : last_sdu_len(0) { - plmns[0].plmn_id.from_number(mcc, mnc); - plmns[0].tac = 0xffff; - } - void init(nas* nas_) { nas_ptr = nas_; } - void write_sdu(unique_byte_buffer_t sdu) - { - last_sdu_len = sdu->N_bytes; - // printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); - // srsran_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); - } - const char* get_rb_name(uint32_t lcid) { return "lcid"; } - uint32_t get_last_sdu_len() { return last_sdu_len; } - void reset() { last_sdu_len = 0; } + nas_args_t nas_cfg; + nas_cfg.force_imsi_attach = true; + nas_cfg.eia = "1,2,3"; + nas_cfg.eea = "0,1,2,3"; + nas_cfg.apn_name = "test123"; - bool plmn_search() - { - nas_ptr->plmn_search_completed(plmns, 1); - return true; - } - void plmn_select(srsran::plmn_id_t plmn_id){}; - void set_ue_identity(srsran::s_tmsi_t s_tmsi) {} - bool connection_request(srsran::establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) - { - printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); - last_sdu_len = sdu->N_bytes; - srsran_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); - is_connected_flag = true; - nas_ptr->connection_request_completed(true); - return true; - } - bool is_connected() { return is_connected_flag; } + test_stack_dummy stack(&pdcp_dummy); + srsue::nas nas(&stack.task_sched); + srsue::gw gw; - uint16_t get_mcc() { return mcc; } - uint16_t get_mnc() { return mnc; } - void enable_capabilities() {} - uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) { return 0; } - void paging_completed(bool outcome) {} - bool has_nr_dc() { return false; } + nas.init(&usim, &rrc_dummy, &gw, nas_cfg); + rrc_dummy.init(&nas); -private: - nas* nas_ptr; - uint32_t last_sdu_len; - nas_interface_rrc::found_plmn_t plmns[nas_interface_rrc::MAX_FOUND_PLMNS]; - bool is_connected_flag = false; -}; + gw_args_t gw_args; + gw_args.tun_dev_name = "tun0"; + gw_args.log.gw_level = "debug"; + gw_args.log.gw_hex_limit = 100000; -class test_stack_dummy : public srsue::stack_test_dummy, public stack_interface_gw, public thread -{ -public: - test_stack_dummy(pdcp_interface_stack* pdcp_) : pdcp(pdcp_), thread("DUMMY STACK") {} - void init(srsue::nas* nas_) - { - nas = nas_; - start(-1); - } - bool switch_on() { return true; } - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); } - bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; } + gw.init(gw_args, &stack); + stack.init(&nas); + // trigger test + stack.switch_on(); + stack.stop(); - bool is_registered() { return true; } + // this will time out in the first place - bool start_service_request() { return true; } + // reset length of last received NAS PDU + rrc_dummy.reset(); - void run_thread() - { - running = true; - while (running) { - task_sched.tic(); - task_sched.run_pending_tasks(); - nas->run_tti(); + // finally push attach accept + byte_buffer_pool* pool = byte_buffer_pool::get_instance(); + unique_byte_buffer_t tmp = srsran::make_byte_buffer(); + TESTASSERT(tmp != nullptr); + memcpy(tmp->msg, attach_accept_pdu, sizeof(attach_accept_pdu)); + tmp->N_bytes = sizeof(attach_accept_pdu); + nas.write_pdu(LCID, std::move(tmp)); + nas_metrics_t metrics; + nas.get_metrics(&metrics); + TESTASSERT(metrics.nof_active_eps_bearer == 1); + + // check length of generated NAS SDU (attach complete) + if (rrc_dummy.get_last_sdu_len() > 3) { + ret = SRSRAN_SUCCESS; } + // ensure buffers are deleted before pool cleanup + gw.stop(); } - void stop() - { - while (not running) { - usleep(1000); - } - running = false; - wait_thread_finish(); - } - pdcp_interface_stack* pdcp = nullptr; - srsue::nas* nas = nullptr; - std::atomic running = {false}; -}; -class gw_dummy : public gw_interface_nas, public gw_interface_pdcp -{ - int setup_if_addr(uint32_t eps_bearer_id, - uint8_t pdn_type, - uint32_t ip_addr, - uint8_t* ipv6_if_id, - char* err_str) - { - return SRSRAN_SUCCESS; - } - int deactivate_eps_bearer(const uint32_t eps_bearer_id) { return SRSRAN_SUCCESS; } - int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) - { - return SRSRAN_SUCCESS; - } - void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) {} - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} - void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms = 0) {} -}; - -} // namespace srsran + return ret; +} int security_command_test() { @@ -246,73 +158,6 @@ int security_command_test() return ret; } -int mme_attach_request_test() -{ - int ret = SRSRAN_ERROR; - - rrc_dummy rrc_dummy; - pdcp_dummy pdcp_dummy; - - srsue::usim usim(srslog::fetch_basic_logger("USIM")); - usim_args_t args; - args.mode = "soft"; - args.algo = "xor"; - args.imei = "353490069873319"; - args.imsi = "001010123456789"; - args.k = "00112233445566778899aabbccddeeff"; - args.op = "63BFA50EE6523365FF14C1F45F88737D"; - usim.init(&args); - - { - nas_args_t nas_cfg; - nas_cfg.force_imsi_attach = true; - nas_cfg.apn_name = "test123"; - - test_stack_dummy stack(&pdcp_dummy); - srsue::nas nas(&stack.task_sched); - srsue::gw gw; - - nas.init(&usim, &rrc_dummy, &gw, nas_cfg); - rrc_dummy.init(&nas); - - gw_args_t gw_args; - gw_args.tun_dev_name = "tun0"; - gw_args.log.gw_level = "debug"; - gw_args.log.gw_hex_limit = 100000; - - gw.init(gw_args, &stack); - stack.init(&nas); - // trigger test - stack.switch_on(); - stack.stop(); - - // this will time out in the first place - - // reset length of last received NAS PDU - rrc_dummy.reset(); - - // finally push attach accept - byte_buffer_pool* pool = byte_buffer_pool::get_instance(); - unique_byte_buffer_t tmp = srsran::make_byte_buffer(); - TESTASSERT(tmp != nullptr); - memcpy(tmp->msg, attach_accept_pdu, sizeof(attach_accept_pdu)); - tmp->N_bytes = sizeof(attach_accept_pdu); - nas.write_pdu(LCID, std::move(tmp)); - nas_metrics_t metrics; - nas.get_metrics(&metrics); - TESTASSERT(metrics.nof_active_eps_bearer == 1); - - // check length of generated NAS SDU (attach complete) - if (rrc_dummy.get_last_sdu_len() > 3) { - ret = SRSRAN_SUCCESS; - } - // ensure buffers are deleted before pool cleanup - gw.stop(); - } - - return ret; -} - int esm_info_request_test() { int ret = SRSRAN_ERROR; @@ -339,6 +184,8 @@ int esm_info_request_test() cfg.apn_name = "srsran"; cfg.apn_user = "srsuser"; cfg.apn_pass = "srspass"; + cfg.eia = "1,2,3"; + cfg.eea = "0,1,2,3"; cfg.force_imsi_attach = true; nas.init(&usim, &rrc_dummy, &gw, cfg); @@ -379,6 +226,8 @@ int dedicated_eps_bearer_test() srsue::nas nas(&stack.task_sched); nas_args_t cfg = {}; cfg.force_imsi_attach = true; // make sure we get a fresh security context + cfg.eia = "1,2,3"; + cfg.eea = "0,1,2,3"; nas.init(&usim, &rrc_dummy, &gw, cfg); // push dedicated EPS bearer PDU to NAS @@ -453,25 +302,10 @@ int main(int argc, char** argv) // Start the log backend. srslog::init(); - if (security_command_test()) { - printf("Security command test failed.\n"); - return -1; - } + TESTASSERT(mme_attach_request_test() == SRSRAN_SUCCESS); + TESTASSERT(security_command_test() == SRSRAN_SUCCESS); + TESTASSERT(esm_info_request_test() == SRSRAN_SUCCESS); + TESTASSERT(dedicated_eps_bearer_test() == SRSRAN_SUCCESS); - if (mme_attach_request_test()) { - printf("Attach request test failed.\n"); - return -1; - } - - if (esm_info_request_test()) { - printf("ESM info request test failed.\n"); - return -1; - } - - if (dedicated_eps_bearer_test()) { - printf("Dedicated EPS bearer test failed.\n"); - return -1; - } - - return 0; + return SRSRAN_SUCCESS; } From 505225d84508f58c9d214ad07858defc95bddcd5 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 7 Jul 2021 16:48:27 +0200 Subject: [PATCH 25/59] Added ue nas base class with security functions --- srsue/hdr/stack/upper/nas.h | 30 +--- srsue/hdr/stack/upper/nas_base.h | 67 ++++++++ srsue/src/stack/upper/CMakeLists.txt | 2 +- srsue/src/stack/upper/nas.cc | 235 ++------------------------ srsue/src/stack/upper/nas_base.cc | 238 +++++++++++++++++++++++++++ 5 files changed, 322 insertions(+), 250 deletions(-) create mode 100644 srsue/hdr/stack/upper/nas_base.h create mode 100644 srsue/src/stack/upper/nas_base.cc diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index eaac627e6..2294096f4 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -13,6 +13,7 @@ #ifndef SRSUE_NAS_H #define SRSUE_NAS_H +#include "nas_base.h" #include "srsran/asn1/liblte_mme.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" @@ -34,7 +35,7 @@ class usim_interface_nas; class gw_interface_nas; class rrc_interface_nas; -class nas : public nas_interface_rrc, public srsran::timer_callback +class nas : public nas_interface_rrc, public srsran::timer_callback, public nas_base { public: explicit nas(srsran::task_sched_handle task_sched_); @@ -71,11 +72,7 @@ public: // timer callback void timer_expired(uint32_t timeout_id) override; - // PCAP - void start_pcap(srsran::nas_pcap* pcap_) { pcap = pcap_; } - private: - srslog::basic_logger& logger; rrc_interface_nas* rrc = nullptr; usim_interface_nas* usim = nullptr; gw_interface_nas* gw = nullptr; @@ -92,18 +89,6 @@ private: std::vector known_plmns; - // Security context - struct nas_sec_ctxt { - uint8_t ksi; - uint8_t k_asme[32]; - uint32_t tx_count; - uint32_t rx_count; - uint32_t k_enb_count; - srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; - srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - }; - typedef enum { DEFAULT_EPS_BEARER = 0, DEDICATED_EPS_BEARER } eps_bearer_type_t; typedef struct { @@ -118,7 +103,6 @@ private: bool have_guti = false; bool have_ctxt = false; - nas_sec_ctxt ctxt = {}; bool auth_request = false; uint8_t current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS; @@ -155,23 +139,13 @@ private: // Security bool eia_caps[8] = {}; bool eea_caps[8] = {}; - uint8_t k_nas_enc[32] = {}; - uint8_t k_nas_int[32] = {}; // Airplane mode simulation typedef enum { DISABLED = 0, ENABLED } airplane_mode_state_t; airplane_mode_state_t airplane_mode_state = {}; srsran::timer_handler::unique_timer airplane_mode_sim_timer; - // PCAP - srsran::nas_pcap* pcap = nullptr; - // Security - void - integrity_generate(uint8_t* key_128, uint32_t count, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); - bool integrity_check(srsran::byte_buffer_t* pdu); - void cipher_encrypt(srsran::byte_buffer_t* pdu); - void cipher_decrypt(srsran::byte_buffer_t* pdu); int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type); void reset_security_context(); void set_k_enb_count(uint32_t count); diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h new file mode 100644 index 000000000..225278146 --- /dev/null +++ b/srsue/hdr/stack/upper/nas_base.h @@ -0,0 +1,67 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_NAS_BASE_H +#define SRSUE_NAS_BASE_H + +#include "srsran/asn1/liblte_mme.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/common/nas_pcap.h" +#include "srsran/common/security.h" +#include "srsran/common/string_helpers.h" +#include "srsran/config.h" + +using srsran::byte_buffer_t; + +namespace srsue { + +class nas_base +{ +public: + nas_base(const std::string& type_); + // PCAP + void start_pcap(srsran::nas_pcap* pcap_) { pcap = pcap_; } + +protected: + srslog::basic_logger& logger; + // PCAP + srsran::nas_pcap* pcap = nullptr; + + // Security context + struct nas_sec_ctxt { + uint8_t ksi; + uint8_t k_asme[32]; + uint32_t tx_count; + uint32_t rx_count; + uint32_t k_enb_count; + srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; + }; + + nas_sec_ctxt ctxt = {}; + uint8_t k_nas_enc[32] = {}; + uint8_t k_nas_int[32] = {}; + + int parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps); + + // Security + void + integrity_generate(uint8_t* key_128, uint32_t count, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); + bool integrity_check(srsran::byte_buffer_t* pdu); + void cipher_encrypt(srsran::byte_buffer_t* pdu); + void cipher_decrypt(srsran::byte_buffer_t* pdu); +}; + +} // namespace srsue +#endif diff --git a/srsue/src/stack/upper/CMakeLists.txt b/srsue/src/stack/upper/CMakeLists.txt index 3038c610c..4d9f1e09f 100644 --- a/srsue/src/stack/upper/CMakeLists.txt +++ b/srsue/src/stack/upper/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(test) -set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc) +set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc) if(HAVE_PCSC) list(APPEND SOURCES "pcsc_usim.cc") diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 1003da37a..7a228a209 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -35,6 +35,7 @@ namespace srsue { ********************************************************************/ nas::nas(srsran::task_sched_handle task_sched_) : + nas_base("NAS"), plmn_searcher(this), task_sched(task_sched_), t3402(task_sched_.get_unique_timer()), @@ -42,8 +43,7 @@ nas::nas(srsran::task_sched_handle task_sched_) : t3411(task_sched_.get_unique_timer()), t3421(task_sched_.get_unique_timer()), reattach_timer(task_sched_.get_unique_timer()), - airplane_mode_sim_timer(task_sched_.get_unique_timer()), - logger(srslog::fetch_basic_logger("NAS")) + airplane_mode_sim_timer(task_sched_.get_unique_timer()) {} int nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& cfg_) @@ -58,30 +58,21 @@ int nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_n } // parse and sanity check EIA list - std::vector cap_list; - srsran::string_parse_list(cfg_.eia, ',', cap_list); - if (cap_list.empty()) { - logger.error("Empty EIA list. Select at least one EIA algorithm."); - } - for (std::vector::const_iterator it = cap_list.begin(); it != cap_list.end(); ++it) { - if (*it != 0 && *it < 4) { - eia_caps[*it] = true; - } else { - logger.error("EIA%d is not a valid EIA algorithm.", *it); - } + if (parse_security_algorithm_list(cfg_.eia, eia_caps) != SRSRAN_SUCCESS) { + logger.warning("Failed to parse integrity protection algorithm list: Defaulting to EIA1-128, EIA2-128, EIA3-128"); + eia_caps[0] = false; + eia_caps[1] = true; + eia_caps[2] = true; + eia_caps[3] = true; } // parse and sanity check EEA list - srsran::string_parse_list(cfg_.eea, ',', cap_list); - if (cap_list.empty()) { - logger.error("Empty EEA list. Select at least one EEA algorithm."); - } - for (std::vector::const_iterator it = cap_list.begin(); it != cap_list.end(); ++it) { - if (*it < 4) { - eea_caps[*it] = true; - } else { - logger.error("EEA%d is not a valid EEA algorithm.", *it); - } + if (parse_security_algorithm_list(cfg_.eea, eea_caps) != SRSRAN_SUCCESS) { + logger.warning("Failed to parse encryption algorithm list: Defaulting to EEA0, EEA1-128, EEA2-128, EEA3-128"); + eea_caps[0] = true; + eea_caps[1] = true; + eea_caps[2] = true; + eea_caps[3] = true; } cfg = cfg_; @@ -689,204 +680,6 @@ void nas::select_plmn() } } -/******************************************************************************* - * Security - ******************************************************************************/ - -void nas::integrity_generate(uint8_t* key_128, - uint32_t count, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac) -{ - switch (ctxt.integ_algo) { - case INTEGRITY_ALGORITHM_ID_EIA0: - break; - case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(key_128, - count, - 0, // Bearer always 0 for NAS - direction, - msg, - msg_len, - mac); - break; - case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(key_128, - count, - 0, // Bearer always 0 for NAS - direction, - msg, - msg_len, - mac); - break; - case INTEGRITY_ALGORITHM_ID_128_EIA3: - security_128_eia3(key_128, - count, - 0, // Bearer always 0 for NAS - direction, - msg, - msg_len, - mac); - break; - default: - break; - } -} - -// This function depends to a valid k_nas_int. -// This key is generated in the security mode command. -bool nas::integrity_check(byte_buffer_t* pdu) -{ - if (pdu == nullptr) { - logger.error("Invalid PDU"); - return false; - } - - if (pdu->N_bytes > 5) { - uint8_t exp_mac[4] = {0}; - uint8_t* mac = &pdu->msg[1]; - - // generate expected MAC - uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; - integrity_generate( - &k_nas_int[16], count_est, SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes - 5, &exp_mac[0]); - - // Check if expected mac equals the sent mac - for (int i = 0; i < 4; i++) { - if (exp_mac[i] != mac[i]) { - logger.warning("Integrity check failure. Local: count=%d, [%02x %02x %02x %02x], " - "Received: count=%d, [%02x %02x %02x %02x]", - count_est, - exp_mac[0], - exp_mac[1], - exp_mac[2], - exp_mac[3], - pdu->msg[5], - mac[0], - mac[1], - mac[2], - mac[3]); - return false; - } - } - logger.info("Integrity check ok. Local: count=%d, Received: count=%d [%02x %02x %02x %02x]", - count_est, - pdu->msg[5], - mac[0], - mac[1], - mac[2], - mac[3]); - - // Updated local count (according to TS 24.301 Sec. 4.4.3.3) - if (count_est != ctxt.rx_count) { - logger.info("Update local count to estimated count %d", count_est); - ctxt.rx_count = count_est; - } - return true; - } else { - logger.error("Invalid integrity check PDU size (%d)", pdu->N_bytes); - return false; - } -} - -void nas::cipher_encrypt(byte_buffer_t* pdu) -{ - byte_buffer_t pdu_tmp; - - if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { - logger.debug("Encrypting PDU. count=%d", ctxt.tx_count); - } - - switch (ctxt.cipher_algo) { - case CIPHERING_ALGORITHM_ID_EEA0: - break; - case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&k_nas_enc[16], - ctxt.tx_count, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); - break; - case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], - ctxt.tx_count, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); - break; - case CIPHERING_ALGORITHM_ID_128_EEA3: - security_128_eea3(&k_nas_enc[16], - ctxt.tx_count, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); - break; - default: - logger.error("Ciphering algorithm not known"); - break; - } -} - -void nas::cipher_decrypt(byte_buffer_t* pdu) -{ - byte_buffer_t tmp_pdu; - - uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; - if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { - logger.debug("Decrypting PDU. Local: count=%d, Received: count=%d", ctxt.rx_count, count_est); - } - - switch (ctxt.cipher_algo) { - case CIPHERING_ALGORITHM_ID_EEA0: - break; - case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&k_nas_enc[16], - count_est, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &tmp_pdu.msg[6]); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); - break; - case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], - count_est, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &tmp_pdu.msg[6]); - logger.debug(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); - break; - case CIPHERING_ALGORITHM_ID_128_EEA3: - security_128_eea3(&k_nas_enc[16], - count_est, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes - 6, - &tmp_pdu.msg[6]); - logger.debug(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); - break; - default: - logger.error("Ciphering algorithms not known"); - break; - } -} bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT* caps) { diff --git a/srsue/src/stack/upper/nas_base.cc b/srsue/src/stack/upper/nas_base.cc new file mode 100644 index 000000000..b4a01f76a --- /dev/null +++ b/srsue/src/stack/upper/nas_base.cc @@ -0,0 +1,238 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsue/hdr/stack/upper/nas_base.h" + +using namespace srsran; +namespace srsue { +nas_base::nas_base(const std::string& type_) : logger(srslog::fetch_basic_logger(type_)) {} + +int nas_base::parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps) +{ + // parse and sanity check security algorithm list + std::vector cap_list; + srsran::string_parse_list(algorithm_string, ',', cap_list); + if (cap_list.empty()) { + logger.error("Empty security list. Select at least one security algorithm."); + return SRSRAN_ERROR; + } + for (std::vector::const_iterator it = cap_list.begin(); it != cap_list.end(); ++it) { + if (*it < 4) { + algorithm_caps[*it] = true; + } else { + logger.error("EEA/EIA/5G-EA/5G-IA %d is not a valid algorithm.", *it); + return SRSRAN_ERROR; + } + } + return SRSRAN_SUCCESS; +} + +/******************************************************************************* + * Security + ******************************************************************************/ + +void nas_base::integrity_generate(uint8_t* key_128, + uint32_t count, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac) +{ + switch (ctxt.integ_algo) { + case INTEGRITY_ALGORITHM_ID_EIA0: + break; + case INTEGRITY_ALGORITHM_ID_128_EIA1: + security_128_eia1(key_128, + count, + 0, // Bearer always 0 for NAS + direction, + msg, + msg_len, + mac); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA2: + security_128_eia2(key_128, + count, + 0, // Bearer always 0 for NAS + direction, + msg, + msg_len, + mac); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(key_128, + count, + 0, // Bearer always 0 for NAS + direction, + msg, + msg_len, + mac); + break; + default: + break; + } +} + +// This function depends to a valid k_nas_int. +// This key is generated in the security mode command. +bool nas_base::integrity_check(byte_buffer_t* pdu) +{ + if (pdu == nullptr) { + logger.error("Invalid PDU"); + return false; + } + + if (pdu->N_bytes > 5) { + uint8_t exp_mac[4] = {0}; + uint8_t* mac = &pdu->msg[1]; + + // generate expected MAC + uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; + integrity_generate( + &k_nas_int[16], count_est, SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes - 5, &exp_mac[0]); + + // Check if expected mac equals the sent mac + for (int i = 0; i < 4; i++) { + if (exp_mac[i] != mac[i]) { + logger.warning("Integrity check failure. Local: count=%d, [%02x %02x %02x %02x], " + "Received: count=%d, [%02x %02x %02x %02x]", + count_est, + exp_mac[0], + exp_mac[1], + exp_mac[2], + exp_mac[3], + pdu->msg[5], + mac[0], + mac[1], + mac[2], + mac[3]); + return false; + } + } + logger.info("Integrity check ok. Local: count=%d, Received: count=%d [%02x %02x %02x %02x]", + count_est, + pdu->msg[5], + mac[0], + mac[1], + mac[2], + mac[3]); + + // Updated local count (according to TS 24.301 Sec. 4.4.3.3) + if (count_est != ctxt.rx_count) { + logger.info("Update local count to estimated count %d", count_est); + ctxt.rx_count = count_est; + } + return true; + } else { + logger.error("Invalid integrity check PDU size (%d)", pdu->N_bytes); + return false; + } +} + +void nas_base::cipher_encrypt(byte_buffer_t* pdu) +{ + byte_buffer_t pdu_tmp; + + if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { + logger.debug("Encrypting PDU. count=%d", ctxt.tx_count); + } + + switch (ctxt.cipher_algo) { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&k_nas_enc[16], + ctxt.tx_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&k_nas_enc[16], + ctxt.tx_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + ctxt.tx_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + break; + default: + logger.error("Ciphering algorithm not known"); + break; + } +} + +void nas_base::cipher_decrypt(byte_buffer_t* pdu) +{ + byte_buffer_t tmp_pdu; + + uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; + if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { + logger.debug("Decrypting PDU. Local: count=%d, Received: count=%d", ctxt.rx_count, count_est); + } + + switch (ctxt.cipher_algo) { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&k_nas_enc[16], + count_est, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&k_nas_enc[16], + count_est, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + logger.debug(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + count_est, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + logger.debug(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + default: + logger.error("Ciphering algorithms not known"); + break; + } +} + +} // namespace srsue \ No newline at end of file From fb92118bb7cd198b1008c0ef54efafb950d13730 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 9 Jul 2021 10:12:31 +0200 Subject: [PATCH 26/59] Add 5G NAS infrastructure --- .../srsran/interfaces/ue_nas_interfaces.h | 11 + .../srsran/interfaces/ue_rrc_interfaces.h | 4 + srsue/hdr/stack/upper/nas_5g.h | 98 ++++++++ srsue/hdr/stack/upper/nas_5g_procedures.h | 40 +++ srsue/hdr/stack/upper/nas_5gmm_state.h | 88 +++++++ srsue/hdr/stack/upper/nas_config.h | 2 + srsue/hdr/stack/upper/test/nas_test_common.h | 29 ++- srsue/src/stack/upper/CMakeLists.txt | 4 +- srsue/src/stack/upper/nas_5g.cc | 236 ++++++++++++++++++ srsue/src/stack/upper/nas_5g_procedures.cc | 38 +++ srsue/src/stack/upper/nas_5gmm_state.cc | 149 +++++++++++ srsue/src/stack/upper/test/CMakeLists.txt | 4 + srsue/src/stack/upper/test/nas_5g_test.cc | 108 ++++++++ 13 files changed, 808 insertions(+), 3 deletions(-) create mode 100644 srsue/hdr/stack/upper/nas_5g.h create mode 100644 srsue/hdr/stack/upper/nas_5g_procedures.h create mode 100644 srsue/hdr/stack/upper/nas_5gmm_state.h create mode 100644 srsue/src/stack/upper/nas_5g.cc create mode 100644 srsue/src/stack/upper/nas_5g_procedures.cc create mode 100644 srsue/src/stack/upper/nas_5gmm_state.cc create mode 100644 srsue/src/stack/upper/test/nas_5g_test.cc diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index fa7f0f47d..e9fe56f43 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -39,6 +39,17 @@ public: virtual bool connection_request_completed(bool outcome) = 0; }; +class nas_5g_interface_rrc_nr +{ +public: +}; + +class nas_5g_interface_procedures +{ +public: + virtual int send_registration_request() = 0; +}; + } // namespace srsue #endif // SRSRAN_UE_NAS_INTERFACES_H diff --git a/lib/include/srsran/interfaces/ue_rrc_interfaces.h b/lib/include/srsran/interfaces/ue_rrc_interfaces.h index 96071af1d..ca1ded8a8 100644 --- a/lib/include/srsran/interfaces/ue_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rrc_interfaces.h @@ -113,6 +113,10 @@ public: virtual bool is_config_pending() = 0; }; +class rrc_nr_interface_nas_5g +{ +public: +}; } // namespace srsue #endif // SRSRAN_UE_RRC_INTERFACES_H diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h new file mode 100644 index 000000000..34171d605 --- /dev/null +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -0,0 +1,98 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_NAS_5G_H +#define SRSUE_NAS_5G_H + +#include "nas_base.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/common.h" +#include "srsran/common/nas_pcap.h" +#include "srsran/common/security.h" +#include "srsran/common/stack_procedure.h" +#include "srsran/common/task_scheduler.h" +#include "srsran/interfaces/ue_gw_interfaces.h" +#include "srsran/interfaces/ue_nas_interfaces.h" +#include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/interfaces/ue_usim_interfaces.h" +#include "srsran/srslog/srslog.h" +#include "srsue/hdr/stack/upper/nas_5gmm_state.h" +#include "srsue/hdr/stack/upper/nas_config.h" + +using srsran::byte_buffer_t; + +namespace srsue { + +class nas_5g : public nas_base, public nas_5g_interface_rrc_nr, public nas_5g_interface_procedures +{ +public: + explicit nas_5g(srsran::task_sched_handle task_sched_); + virtual ~nas_5g(); + int init(usim_interface_nas* usim_, rrc_nr_interface_nas_5g* rrc_nr_, gw_interface_nas* gw_, const nas_args_t& cfg_); + void stop(); + void run_tti(); + + // Stack+RRC interface + bool is_registered(); + + // timer callback + void timer_expired(uint32_t timeout_id); + + // Stack interface + int switch_on(); + int switch_off(); + int enable_data(); + int disable_data(); + int start_service_request(); + +private: + rrc_nr_interface_nas_5g* rrc_nr = nullptr; + usim_interface_nas* usim = nullptr; + gw_interface_nas* gw = nullptr; + + bool running = false; + + nas_args_t cfg = {}; + mm5g_state_t state = {}; + + // Security + bool ia5g_caps[8] = {}; + bool ea5g_caps[8] = {}; + + // timers + srsran::task_sched_handle task_sched; + srsran::timer_handler::unique_timer t3502; // started when registration failure and the attempt counter is equal to 5 + srsran::timer_handler::unique_timer t3510; // started when transmission of REGISTRATION REQUEST message. ON EXPIRY: + // start T3511 or T3502 as specified in subclause 5.5.1.2.7 + srsran::timer_handler::unique_timer t3511; // started when registration failure due to lower layer failure + srsran::timer_handler::unique_timer t3521; // started when detach request is sent + srsran::timer_handler::unique_timer reregistration_timer; // started to trigger delayed re-attach + + // Values according to TS 24.501 Sec 10.2 + const uint32_t t3502_duration_ms = 12 * 60 * 1000; // 12m + const uint32_t t3510_duration_ms = 15 * 1000; // 15s + const uint32_t t3511_duration_ms = 10 * 1000; // 10s + const uint32_t t3521_duration_ms = 15 * 1000; // 15s + const uint32_t reregistration_timer_duration_ms = 2 * 1000; // 2s (arbitrarily chosen to delay re-attach) + + srsran::proc_manager_list_t callbacks; + + // Procedures + // Forward declartion + class registration_procedure; + + srsran::proc_t registration_proc; + + int send_registration_request(); +}; +} // namespace srsue +#endif \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_5g_procedures.h b/srsue/hdr/stack/upper/nas_5g_procedures.h new file mode 100644 index 000000000..85ef15bcd --- /dev/null +++ b/srsue/hdr/stack/upper/nas_5g_procedures.h @@ -0,0 +1,40 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_NAS_5G_PROCEDURES_H_ +#define SRSUE_NAS_5G_PROCEDURES_H_ + +#include "srsue/hdr/stack/upper/nas_5g.h" + +namespace srsue { + +/** + * @brief 5G NAS registration procedure + * + * Specified in 24 501 V16.7.0 + * 5GMM specific procedures + * 5.5.1 Registration procedure + */ +class nas_5g::registration_procedure +{ +public: + explicit registration_procedure(nas_5g_interface_procedures* parent_nas_); + srsran::proc_outcome_t init(); + srsran::proc_outcome_t step(); + static const char* name() { return "Registration Procedure"; } + +private: + nas_5g_interface_procedures* parent_nas; +}; +} // namespace srsue + +#endif // SRSUE_NAS_5G_PROCEDURES_H_ \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_5gmm_state.h b/srsue/hdr/stack/upper/nas_5gmm_state.h new file mode 100644 index 000000000..29fb2a983 --- /dev/null +++ b/srsue/hdr/stack/upper/nas_5gmm_state.h @@ -0,0 +1,88 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_NR_NAS_MM5G_STATE_H +#define SRSUE_NR_NAS_MM5G_STATE_H + +#include "srsran/srslog/srslog.h" +#include +#include + +namespace srsue { + +// 5GMM states (3GPP 24.501 v16.07.0) +class mm5g_state_t +{ +public: + enum class state_t { + null = 0, + deregistered, + registered_initiated, + registered, + deregistered_initiated, + service_request_initiated, + }; + + // 5GMM-DEREGISTERED sub-states (3GPP 24.501 v16.07.0) + enum class deregistered_substate_t { + null = 0, // This should be used when not in mm5g-DEREGISTERED + normal_service, + limited_service, + attempting_to_registration, + plmn_search, + no_supi, + no_cell_available, + e_call_inactive, + initial_registration_needed, + }; + + // 5GMM-DEREGISTERED sub-states (3GPP 24.501 v16.07.0) + enum class registered_substate_t { + null = 0, // This should be used when not in mm5g-REGISTERED + normal_service, + non_allowed_service, + attempting_registration_update, + limited_service, + plmn_search, + no_cell_available, + update_needed, + }; + + // FSM setters + void set_null(); + void set_deregistered(deregistered_substate_t substate); + void set_deregistered_initiated(); + void set_registered(registered_substate_t substate); + void set_registered_initiated(); + void set_service_request_initiated(); + + // FSM getters + state_t get_state() { return state; } + deregistered_substate_t get_deregistered_substate() { return deregistered_substate; } + registered_substate_t get_registered_substate() { return registered_substate; } + + // Text Helpers + const std::string get_full_state_text(); + +private: + std::atomic state{state_t::null}; + deregistered_substate_t deregistered_substate = deregistered_substate_t::null; + registered_substate_t registered_substate = registered_substate_t::null; + srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS-5G"); +}; + +const char* mm5g_state_text(mm5g_state_t::state_t type); +const char* mm5g_deregistered_substate_text(mm5g_state_t::deregistered_substate_t type); +const char* mm5g_registered_substate_text(mm5g_state_t::registered_substate_t type); + +} // namespace srsue +#endif diff --git a/srsue/hdr/stack/upper/nas_config.h b/srsue/hdr/stack/upper/nas_config.h index 1836b7fce..179b0f7fa 100644 --- a/srsue/hdr/stack/upper/nas_config.h +++ b/srsue/hdr/stack/upper/nas_config.h @@ -34,6 +34,8 @@ public: bool force_imsi_attach; std::string eia; std::string eea; + std::string ia5g; + std::string ea5g; nas_sim_args_t sim; }; diff --git a/srsue/hdr/stack/upper/test/nas_test_common.h b/srsue/hdr/stack/upper/test/nas_test_common.h index 1af31d3c7..faa40bf51 100644 --- a/srsue/hdr/stack/upper/test/nas_test_common.h +++ b/srsue/hdr/stack/upper/test/nas_test_common.h @@ -22,6 +22,7 @@ #include "srsran/test/ue_test_interfaces.h" #include "srsue/hdr/stack/upper/gw.h" #include "srsue/hdr/stack/upper/nas.h" +#include "srsue/hdr/stack/upper/nas_5g.h" #include "srsue/hdr/stack/upper/usim.h" #include "srsue/hdr/stack/upper/usim_base.h" @@ -122,6 +123,26 @@ private: bool is_connected_flag = false; }; +class rrc_nr_dummy : public rrc_nr_interface_nas_5g +{ +public: + rrc_nr_dummy() : last_sdu_len(0) + { + plmns[0].plmn_id.from_number(mcc, mnc); + plmns[0].tac = 0xffff; + } + void init(nas_5g* nas_5g_) { nas_5g_ptr = nas_5g_; } + void write_sdu(unique_byte_buffer_t sdu) + { + last_sdu_len = sdu->N_bytes; + // printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + } + +private: + nas_5g* nas_5g_ptr; + uint32_t last_sdu_len; + nas_interface_rrc::found_plmn_t plmns[nas_interface_rrc::MAX_FOUND_PLMNS]; +}; template class test_stack_dummy : public srsue::stack_test_dummy, public stack_interface_gw, public thread { @@ -132,7 +153,11 @@ public: nas = nas_; start(-1); } - bool switch_on() { nas->switch_on(); return true; } + bool switch_on() + { + nas->switch_on(); + return true; + } void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); } bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; } @@ -158,7 +183,7 @@ public: wait_thread_finish(); } pdcp_interface_stack* pdcp = nullptr; - T* nas = nullptr; + T* nas = nullptr; std::atomic running = {false}; }; diff --git a/srsue/src/stack/upper/CMakeLists.txt b/srsue/src/stack/upper/CMakeLists.txt index 4d9f1e09f..29c26f205 100644 --- a/srsue/src/stack/upper/CMakeLists.txt +++ b/srsue/src/stack/upper/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(test) -set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc) +set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc nas_5g_procedures.cc nas_5g.cc nas_5gmm_state.cc) if(HAVE_PCSC) list(APPEND SOURCES "pcsc_usim.cc") @@ -17,6 +17,8 @@ endif(HAVE_PCSC) add_library(srsue_upper STATIC ${SOURCES}) target_link_libraries(srsue_upper ${ATOMIC_LIBS} srsran_asn1) +target_link_libraries(srsue_upper nas_5g_msg) + if(HAVE_PCSC) target_link_libraries(srsue_upper ${PCSCLITE_LIBRARY}) endif(HAVE_PCSC) \ No newline at end of file diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc new file mode 100644 index 000000000..97718fc75 --- /dev/null +++ b/srsue/src/stack/upper/nas_5g.cc @@ -0,0 +1,236 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsue/hdr/stack/upper/nas_5g.h" +#include "srsran/asn1/nas_5g_ies.h" +#include "srsran/asn1/nas_5g_msg.h" +#include "srsran/common/bcd_helpers.h" +#include "srsran/common/security.h" +#include "srsran/common/standard_streams.h" +#include "srsran/common/string_helpers.h" +#include "srsran/interfaces/ue_gw_interfaces.h" +#include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/interfaces/ue_usim_interfaces.h" +#include "srsue/hdr/stack/upper/nas_5g_procedures.h" + +#include +#include +#include +#include + +using namespace srsran; +using namespace srsran::nas_5g; + +namespace srsue { + +/********************************************************************* + * NAS 5G (NR) + ********************************************************************/ + +nas_5g::nas_5g(srsran::task_sched_handle task_sched_) : + nas_base("NAS-5G"), + task_sched(task_sched_), + t3502(task_sched_.get_unique_timer()), + t3510(task_sched_.get_unique_timer()), + t3511(task_sched_.get_unique_timer()), + t3521(task_sched_.get_unique_timer()), + reregistration_timer(task_sched_.get_unique_timer()), + registration_proc(this) +{ + // Configure timers + t3502.set(t3502_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); + t3510.set(t3510_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); + t3511.set(t3511_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); + t3521.set(t3521_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); + reregistration_timer.set(reregistration_timer_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); +} + +nas_5g::~nas_5g() {} + +void nas_5g::stop() +{ + running = false; +} + +int nas_5g::init(usim_interface_nas* usim_, + rrc_nr_interface_nas_5g* rrc_nr_, + gw_interface_nas* gw_, + const nas_args_t& cfg_) +{ + usim = usim_; + rrc_nr = rrc_nr_; + gw = gw_; + cfg = cfg_; + + // parse and sanity check EIA list + if (parse_security_algorithm_list(cfg_.ia5g, ia5g_caps) != SRSRAN_SUCCESS) { + logger.warning("Failed to parse integrity algorithm list: Defaulting to 5G-EI1-128, 5G-EI2-128, 5G-EI3-128"); + ia5g_caps[0] = false; + ia5g_caps[1] = true; + ia5g_caps[2] = true; + ia5g_caps[3] = true; + } + + // parse and sanity check EEA list + if (parse_security_algorithm_list(cfg_.ea5g, ea5g_caps) != SRSRAN_SUCCESS) { + logger.warning( + "Failed to parse encryption algorithm list: Defaulting to 5G-EA0, 5G-EA1-128, 5G-EA2-128, 5G-EA3-128"); + ea5g_caps[0] = true; + ea5g_caps[1] = true; + ea5g_caps[2] = true; + ea5g_caps[3] = true; + } + + running = true; + return SRSRAN_SUCCESS; +} + +void nas_5g::run_tti() +{ + // Process PLMN selection ongoing procedures + callbacks.run(); + + // Transmit intiating messages if necessary + switch (state.get_state()) { + case mm5g_state_t::state_t::deregistered: + // TODO Make sure cell selection is finished after transitioning from another state (if required) + // Make sure the RRC is finished transitioning to RRC Idle + if (reregistration_timer.is_running()) { + logger.debug("Waiting for re-attach timer to expire to attach again."); + return; + } + switch (state.get_deregistered_substate()) { + case mm5g_state_t::deregistered_substate_t::plmn_search: + case mm5g_state_t::deregistered_substate_t::normal_service: + case mm5g_state_t::deregistered_substate_t::initial_registration_needed: + registration_proc.launch(); + break; + case mm5g_state_t::deregistered_substate_t::attempting_to_registration: + case mm5g_state_t::deregistered_substate_t::no_supi: + case mm5g_state_t::deregistered_substate_t::no_cell_available: + case mm5g_state_t::deregistered_substate_t::e_call_inactive: + logger.debug("Attempting to registration (not implemented) %s", state.get_full_state_text().c_str()); + default: + break; + } + case mm5g_state_t::state_t::registered: + break; + case mm5g_state_t::state_t::deregistered_initiated: + logger.debug("UE detaching..."); + break; + default: + break; + } +} + +/******************************************************************************* + * Senders + ******************************************************************************/ + +int nas_5g::send_registration_request() +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating registration request"); + + nas_5gs_msg nas_msg; + registration_request_t& reg_req = nas_msg.set_registration_request(); + + reg_req.registration_type_5gs.follow_on_request_bit = + registration_type_5gs_t::follow_on_request_bit_type_::options::no_follow_on_request_pending; + reg_req.registration_type_5gs.registration_type = + registration_type_5gs_t::registration_type_type_::options::initial_registration; + mobile_identity_5gs_t::suci_s& suci = reg_req.mobile_identity_5gs.set_suci(); + suci.supi_format = mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi; + mcc_to_bytes(0x0, suci.mcc.data()); + uint8_t mnc_len; + mnc_to_bytes(0x0, suci.mnc.data(), &mnc_len); + suci.scheme_output.resize(15); + usim->get_imsi_vec(suci.scheme_output.data(), 15); + logger.info("Requesting IMSI attach (IMSI=%s)", usim->get_imsi_str().c_str()); + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack registration request"); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + // start T3510 + logger.debug("Starting T3410. Timeout in %d ms.", t3510.duration()); + t3510.run(); + + state.set_registered_initiated(); + + return SRSRAN_SUCCESS; +} + +/******************************************************************************* + * UE Stack and RRC common Interface + ******************************************************************************/ +bool nas_5g::is_registered() +{ + return state.get_state() == mm5g_state_t::state_t::registered; +} + +/******************************************************************************* + * NAS Timers + ******************************************************************************/ +void nas_5g::timer_expired(uint32_t timeout_id) +{ + // TODO +} + +/******************************************************************************* + * UE Stack Interface + ******************************************************************************/ +int nas_5g::switch_on() +{ + logger.info("Switching on"); + state.set_deregistered(mm5g_state_t::deregistered_substate_t::plmn_search); + return SRSRAN_SUCCESS; +} + +int nas_5g::switch_off() +{ + logger.info("Switching off"); + // TODO + return SRSRAN_SUCCESS; +} + +int nas_5g::enable_data() +{ + logger.info("Enabling data services"); + return switch_on(); +} + +int nas_5g::disable_data() +{ + logger.info("Disabling data services"); + // TODO + return SRSRAN_SUCCESS; +} + +int nas_5g::start_service_request() +{ + logger.info("Service Request"); + // TODO + return SRSRAN_SUCCESS; +} + +} // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/upper/nas_5g_procedures.cc b/srsue/src/stack/upper/nas_5g_procedures.cc new file mode 100644 index 000000000..bf2b80e2d --- /dev/null +++ b/srsue/src/stack/upper/nas_5g_procedures.cc @@ -0,0 +1,38 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsue/hdr/stack/upper/nas_5g_procedures.h" + +#include +#include +#include +#include + +using namespace srsran; + +namespace srsue { + +nas_5g::registration_procedure::registration_procedure(nas_5g_interface_procedures* parent_nas_) : + parent_nas(parent_nas_) +{} + +srsran::proc_outcome_t nas_5g::registration_procedure::init() +{ + parent_nas->send_registration_request(); + return srsran::proc_outcome_t::yield; +} +srsran::proc_outcome_t nas_5g::registration_procedure::step() +{ + return srsran::proc_outcome_t::success; +} + +} // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/upper/nas_5gmm_state.cc b/srsue/src/stack/upper/nas_5gmm_state.cc new file mode 100644 index 000000000..cc8ba316e --- /dev/null +++ b/srsue/src/stack/upper/nas_5gmm_state.cc @@ -0,0 +1,149 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#include "srsue/hdr/stack/upper/nas_5gmm_state.h" + +namespace srsue { + +// FSM setters +void mm5g_state_t::set_null() +{ + state = state_t::null; + deregistered_substate = deregistered_substate_t::null; + registered_substate = registered_substate_t::null; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +void mm5g_state_t::set_deregistered(deregistered_substate_t substate) +{ + state = state_t::deregistered; + deregistered_substate = substate; + registered_substate = registered_substate_t::null; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +void mm5g_state_t::set_deregistered_initiated() +{ + state = state_t::deregistered_initiated; + deregistered_substate = deregistered_substate_t::null; + registered_substate = registered_substate_t::null; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +void mm5g_state_t::set_registered(registered_substate_t substate) +{ + state = state_t::registered; + deregistered_substate = deregistered_substate_t::null; + registered_substate = substate; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +void mm5g_state_t::set_registered_initiated() +{ + state = state_t::registered_initiated; + deregistered_substate = deregistered_substate_t::null; + registered_substate = registered_substate_t::null; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +void mm5g_state_t::set_service_request_initiated() +{ + state = state_t::service_request_initiated; + deregistered_substate = deregistered_substate_t::null; + registered_substate = registered_substate_t::null; + logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str()); +} + +const std::string mm5g_state_t::get_full_state_text() +{ + if (state == state_t::deregistered) { + return mm5g_state_text(state) + std::string(", with substate ") + + mm5g_deregistered_substate_text(deregistered_substate); + } else if (state == state_t::registered) { + return mm5g_state_text(state) + std::string(", with substate ") + + mm5g_registered_substate_text(registered_substate); + } else { + return mm5g_state_text(state); + } + return std::string("Invalid State"); +} + +/* + * Logging helper functions + */ +const char* mm5g_state_text(mm5g_state_t::state_t type) +{ + switch (type) { + case mm5g_state_t::state_t::null: + return "NULL"; + case mm5g_state_t::state_t::deregistered: + return "DEREGISTERED"; + case mm5g_state_t::state_t::registered_initiated: + return "REGISTERED-INITIATED"; + case mm5g_state_t::state_t::registered: + return "REGISTERED"; + case mm5g_state_t::state_t::deregistered_initiated: + return "DEREGISTERED-INITIATED"; + case mm5g_state_t::state_t::service_request_initiated: + return "SERVICE-REQUEST-INITIATED"; + } + return "INVALID"; +} + +const char* mm5g_deregistered_substate_text(mm5g_state_t::deregistered_substate_t type) +{ + switch (type) { + case mm5g_state_t::deregistered_substate_t::null: + return "NULL"; + case mm5g_state_t::deregistered_substate_t::normal_service: + return "NORMAL-SERVICE"; + case mm5g_state_t::deregistered_substate_t::limited_service: + return "LIMITED-SERVICE"; + case mm5g_state_t::deregistered_substate_t::attempting_to_registration: + return "ATTEMPTING-TO-REGISTRATION"; + case mm5g_state_t::deregistered_substate_t::plmn_search: + return "PLMN-SEARCH"; + case mm5g_state_t::deregistered_substate_t::no_supi: + return "NO-SUPI"; + case mm5g_state_t::deregistered_substate_t::no_cell_available: + return "NO-CELL-AVAILABLE"; + case mm5g_state_t::deregistered_substate_t::e_call_inactive: + return "eCALL-INACTIVE"; + case mm5g_state_t::deregistered_substate_t::initial_registration_needed: + return "ATTACH-NEEDED"; + } + return "INVALID"; +} + +const char* mm5g_registered_substate_text(mm5g_state_t::registered_substate_t type) +{ + switch (type) { + case mm5g_state_t::registered_substate_t::null: + return "NULL"; + case mm5g_state_t::registered_substate_t::normal_service: + return "NORMAL-SERVICE"; + case mm5g_state_t::registered_substate_t::non_allowed_service: + return "NON-ALLOWED-SERVICE"; + case mm5g_state_t::registered_substate_t::attempting_registration_update: + return "ATTEMPTING-REGISTRATION-UPDATE"; + case mm5g_state_t::registered_substate_t::limited_service: + return "LIMITED-SERVICE"; + case mm5g_state_t::registered_substate_t::plmn_search: + return "PLMN-SEARCH"; + case mm5g_state_t::registered_substate_t::no_cell_available: + return "NO-CELL-AVAILABLE"; + case mm5g_state_t::registered_substate_t::update_needed: + return "UPDATE-NEEDED"; + } + return "INVALID"; +} + +} // namespace srsue diff --git a/srsue/src/stack/upper/test/CMakeLists.txt b/srsue/src/stack/upper/test/CMakeLists.txt index 56dc8c469..8ba97816a 100644 --- a/srsue/src/stack/upper/test/CMakeLists.txt +++ b/srsue/src/stack/upper/test/CMakeLists.txt @@ -19,6 +19,10 @@ add_executable(nas_test nas_test.cc) target_link_libraries(nas_test srsue_upper srsran_common srsran_phy rrc_asn1 srsran_asn1) add_test(nas_test nas_test) +add_executable(nas_5g_test nas_5g_test.cc) +target_link_libraries(nas_5g_test srsue_upper srsran_phy rrc_asn1) +add_test(nas_5g_test nas_5g_test) + add_executable(gw_test gw_test.cc) target_link_libraries(gw_test srsue_upper srsran_common srsran_phy) add_test(gw_test gw_test) diff --git a/srsue/src/stack/upper/test/nas_5g_test.cc b/srsue/src/stack/upper/test/nas_5g_test.cc new file mode 100644 index 000000000..8556e326a --- /dev/null +++ b/srsue/src/stack/upper/test/nas_5g_test.cc @@ -0,0 +1,108 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/common/bcd_helpers.h" +#include "srsran/common/test_common.h" +#include "srsran/common/tsan_options.h" +#include "srsran/interfaces/ue_pdcp_interfaces.h" +#include "srsran/srslog/srslog.h" +#include "srsran/test/ue_test_interfaces.h" +#include "srsue/hdr/stack/upper/gw.h" +#include "srsue/hdr/stack/upper/nas_5g.h" +#include "srsue/hdr/stack/upper/test/nas_test_common.h" + +using namespace srsue; +using namespace srsran; + +#define HAVE_PCAP 0 + +int amf_attach_request_test(srsran::nas_pcap* pcap) +{ + int ret = SRSRAN_ERROR; + + rrc_nr_dummy rrc_nr_dummy; + pdcp_dummy pdcp_dummy; + + srsue::usim usim(srslog::fetch_basic_logger("USIM")); + usim_args_t args; + args.mode = "soft"; + args.algo = "xor"; + args.imei = "353490069873319"; + args.imsi = "001010123456789"; + args.k = "00112233445566778899aabbccddeeff"; + args.op = "63BFA50EE6523365FF14C1F45F88737D"; + usim.init(&args); + + nas_args_t nas_cfg; + nas_cfg.force_imsi_attach = true; + nas_cfg.apn_name = "test123"; + nas_cfg.ia5g = "0,1,2,3"; + nas_cfg.ea5g = "0,1,2,3"; + + test_stack_dummy stack(&pdcp_dummy); + srsue::nas_5g nas_5g(&stack.task_sched); + srsue::gw gw; + + if (pcap != nullptr) { + nas_5g.start_pcap(pcap); + } + + gw_args_t gw_args; + gw_args.tun_dev_name = "tun0"; + gw_args.log.gw_level = "debug"; + gw_args.log.gw_hex_limit = 100000; + + gw.init(gw_args, &stack); + stack.init(&nas_5g); + + nas_5g.init(&usim, &rrc_nr_dummy, &gw, nas_cfg); + rrc_nr_dummy.init(&nas_5g); + + // trigger test + stack.switch_on(); + stack.stop(); + + gw.stop(); + ret = SRSRAN_SUCCESS; + + return ret; +} + +int main(int argc, char** argv) +{ + // Setup logging. + auto& rrc_logger = srslog::fetch_basic_logger("RRC", false); + rrc_logger.set_level(srslog::basic_levels::debug); + rrc_logger.set_hex_dump_max_size(100000); + auto& nas_logger = srslog::fetch_basic_logger("NAS", false); + nas_logger.set_level(srslog::basic_levels::debug); + nas_logger.set_hex_dump_max_size(100000); + auto& usim_logger = srslog::fetch_basic_logger("USIM", false); + usim_logger.set_level(srslog::basic_levels::debug); + usim_logger.set_hex_dump_max_size(100000); + auto& gw_logger = srslog::fetch_basic_logger("GW", false); + gw_logger.set_level(srslog::basic_levels::debug); + gw_logger.set_hex_dump_max_size(100000); + + // Start the log backend. + srslog::init(); +#if HAVE_PCAP + srsran::nas_pcap pcap; + pcap.open("nas_5g_test.pcap", 0, srsran::srsran_rat_t::nr); + TESTASSERT(amf_attach_request_test(&pcap) == SRSRAN_SUCCESS); + pcap.close(); +#else + TESTASSERT(amf_attach_request_test(nullptr) == SRSRAN_SUCCESS); +#endif // HAVE_PCAP + + return SRSRAN_SUCCESS; +} From b25681f9ded063cbd3d9e6ceaf03ae7566070b5e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 13 Jul 2021 23:23:01 +0200 Subject: [PATCH 27/59] gnb,prach: add PRACH to gNB rebase of Xavier's feature_gnb_prach branch --- .../srsran/interfaces/gnb_interfaces.h | 67 +++++----- lib/include/srsran/phy/phch/dci_nr.h | 8 +- lib/src/common/phy_cfg_nr_default.cc | 3 +- srsenb/hdr/phy/nr/slot_worker.h | 13 +- srsenb/hdr/phy/nr/worker_pool.h | 56 +++++++++ srsenb/hdr/stack/gnb_stack_nr.h | 1 + srsenb/hdr/stack/mac/mac_nr.h | 5 +- srsenb/src/phy/nr/slot_worker.cc | 57 +++++---- srsenb/src/phy/nr/worker_pool.cc | 83 ++++++++++++- srsenb/src/stack/gnb_stack_nr.cc | 2 + srsenb/src/stack/mac/nr/mac_nr.cc | 114 +----------------- srsue/hdr/phy/nr/worker_pool.h | 18 ++- srsue/src/phy/nr/sf_worker.cc | 1 + srsue/src/phy/nr/worker_pool.cc | 9 +- test/phy/CMakeLists.txt | 15 ++- test/phy/dummy_gnb_stack.h | 43 +++++-- test/phy/dummy_ue_stack.h | 58 +++++++-- test/phy/nr_phy_test.cc | 64 +++++++--- test/phy/test_bench.h | 31 ++++- 19 files changed, 414 insertions(+), 234 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 0ed3595ba..71b5d424d 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -162,42 +162,31 @@ public: virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; }; -class phy_interface_stack_nr +class phy_interface_rrc_nr { public: - const static int MAX_DL_GRANTS = 4; + /** + * @brief Describes physical layer configuration common among all the UEs for a given cell + */ + struct common_cfg_t { + srsran_carrier_nr_t carrier; + srsran_pdcch_cfg_nr_t pdcch; + srsran_prach_cfg_t prach; + }; - typedef struct { - // TODO: include NR related fields - } dl_sched_grant_t; + virtual int set_common_cfg(const common_cfg_t& common_cfg) = 0; +}; - typedef struct { - bool mib_present; - } bch_sched_t; +class phy_interface_mac_nr +{ +public: + // TBD +}; - typedef struct { - uint32_t tti; - uint32_t nof_grants; - dl_sched_grant_t pdsch[MAX_DL_GRANTS]; - int beam_id; - } dl_config_request_t; - - typedef struct { - bch_sched_t pbch; - uint16_t length; - uint16_t index; // index indicated in dl_config - uint8_t* data[SRSRAN_MAX_TB]; // always a pointer in our case - } tx_request_pdu_t; - - typedef struct { - uint32_t tti; - uint32_t tb_len; - uint32_t nof_pdus; - tx_request_pdu_t pdus[MAX_DL_GRANTS]; - } tx_request_t; - - virtual int dl_config_request(const dl_config_request_t& request) = 0; - virtual int tx_request(const tx_request_t& request) = 0; +class phy_interface_stack_nr : public phy_interface_rrc_nr, public phy_interface_mac_nr +{ +public: + // TBD }; class stack_interface_mac @@ -271,11 +260,17 @@ public: // ... add signal measurements here }; - virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; - virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; - virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; - virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0; - virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) = 0; + struct rach_info_t { + uint32_t preamble; + uint32_t time_adv; + }; + + virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0; + virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0; + virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0; + virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0; + virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) = 0; + virtual void rach_detected(const rach_info_t& rach_info) = 0; }; class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr diff --git a/lib/include/srsran/phy/phch/dci_nr.h b/lib/include/srsran/phy/phch/dci_nr.h index 92986c1a8..ae3c037bd 100644 --- a/lib/include/srsran/phy/phch/dci_nr.h +++ b/lib/include/srsran/phy/phch/dci_nr.h @@ -147,8 +147,14 @@ typedef struct SRSRAN_API { uint32_t pid; ///< HARQ process number uint32_t dai; ///< Downlink assignment index uint32_t tpc; ///< TPC command for scheduled PUCCH - uint32_t pucch_resource; ///< PUCCH resource indicator + uint32_t pucch_resource; ///< PUCCH resource indicator for HARQ feedback + ///< @note PUCCH resource is selected from PUCCH-ResourceSet if available, otherwise the UE + ///< shall pick a pucch-ResourceCommon from Table 9.2.1-1. uint32_t harq_feedback; ///< PDSCH-to-HARQ_feedback timing indicator + ///< @note harq_feedback for format 1_0 indicates the delay between the PDSCH reception and + ///< the UL transmission timing + ///< @note harq_feedback for format 1_1 is index of the delay indicated in DL data to UL ACK + ///< dedicated configuration table // P-RNTI specific fields uint32_t smi; ///< Short Messages Indicator diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index abb3fd39a..511045284 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -197,6 +197,7 @@ void phy_cfg_nr_default_t::make_prach_default_lte(srsran_prach_cfg_t& prach) prach.config_idx = 0; prach.freq_offset = 2; prach.root_seq_idx = 0; + prach.is_nr = true; } phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) @@ -250,4 +251,4 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) } } -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index ec079f4a2..b86a53986 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -32,12 +32,11 @@ class slot_worker final : public srsran::thread_pool::worker { public: struct args_t { - uint32_t cell_index = 0; - srsran_carrier_nr_t carrier = {}; - uint32_t nof_tx_ports = 1; - uint32_t nof_rx_ports = 1; - uint32_t pusch_max_nof_iter = 10; - srsran_pdcch_cfg_nr_t pdcch_cfg = {}; ///< PDCCH configuration + uint32_t cell_index = 0; + uint32_t nof_max_prb = SRSRAN_MAX_PRB_NR; + uint32_t nof_tx_ports = 1; + uint32_t nof_rx_ports = 1; + uint32_t pusch_max_nof_iter = 10; }; slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger); @@ -45,6 +44,8 @@ public: bool init(const args_t& args); + bool set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_); + /* Functions used by main PHY thread */ cf_t* get_buffer_rx(uint32_t antenna_idx); cf_t* get_buffer_tx(uint32_t antenna_idx); diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 580aa22fe..28d8085bb 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -15,7 +15,9 @@ #include "slot_worker.h" #include "srsenb/hdr/phy/phy_interfaces.h" +#include "srsenb/hdr/phy/prach_worker.h" #include "srsran/common/thread_pool.h" +#include "srsran/interfaces/enb_mac_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" namespace srsenb { @@ -23,11 +25,64 @@ namespace nr { class worker_pool { +private: + class prach_stack_adaptor_t : public stack_interface_phy_lte + { + private: + stack_interface_phy_nr& stack; + + public: + prach_stack_adaptor_t(stack_interface_phy_nr& stack_) : stack(stack_) + { + // Do nothing + } + + int sr_detected(uint32_t tti, uint16_t rnti) override { return 0; } + void rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) override + { + stack_interface_phy_nr::rach_info_t rach_info = {}; + rach_info.preamble = preamble_idx; + rach_info.time_adv = time_adv; + + stack.rach_detected(rach_info); + } + int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) override { return 0; } + int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) override { return 0; } + int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) override { return 0; } + int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) override { return 0; } + int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override { return 0; } + int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) override { return 0; } + int crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) override { return 0; } + int push_pdu(uint32_t tti_rx, + uint16_t rnti, + uint32_t enb_cc_idx, + uint32_t nof_bytes, + bool crc_res, + uint32_t ul_nof_prbs) override + { + return 0; + } + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override { return 0; } + int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) override { return 0; } + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } + void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {} + void tti_clock() override {} + }; + srsran::phy_common_interface& common; stack_interface_phy_nr& stack; srslog::sink& log_sink; srsran::thread_pool pool; std::vector > workers; + prach_worker_pool prach; + uint32_t current_tti = 0; ///< Current TTI, read and write from same thread + srslog::basic_logger& logger; + prach_stack_adaptor_t prach_stack_adaptor; + + // Current configuration + std::mutex common_cfg_mutex; + srsran_carrier_nr_t carrier = {}; + srsran_pdcch_cfg_nr_t pdcch_cfg = {}; public: struct args_t { @@ -47,6 +102,7 @@ public: slot_worker* wait_worker_id(uint32_t id); void start_worker(slot_worker* w); void stop(); + int set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common_cfg); }; } // namespace nr diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 556e349a8..c0dc96a69 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -77,6 +77,7 @@ public: int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; + void rach_detected(const rach_info_t& rach_info) override; private: void run_thread() final; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 418fa1dc2..7fec1d1f8 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -71,12 +71,9 @@ public: int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override; int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override; + void rach_detected(const rach_info_t& rach_info) override; private: - void get_dl_config(const uint32_t tti, - phy_interface_stack_nr::dl_config_request_t& config_request, - phy_interface_stack_nr::tx_request_t& tx_request); - // PDU processing int handle_pdu(srsran::unique_byte_buffer_t pdu); diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 4ff00a180..44ff4271f 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -26,11 +26,12 @@ slot_worker::slot_worker(srsran::phy_common_interface& common_, bool slot_worker::init(const args_t& args) { // Calculate subframe length - sf_len = SRSRAN_SF_LEN_PRB_NR(args.carrier.nof_prb); + sf_len = SRSRAN_SF_LEN_PRB_NR(args.nof_max_prb); // Copy common configurations cell_index = args.cell_index; - pdcch_cfg = args.pdcch_cfg; + // FIXME: + // pdcch_cfg = args.pdcch_cfg; // Allocate Tx buffers tx_buffer.resize(args.nof_tx_ports); @@ -55,10 +56,10 @@ bool slot_worker::init(const args_t& args) // Prepare DL arguments srsran_gnb_dl_args_t dl_args = {}; dl_args.pdsch.measure_time = true; - dl_args.pdsch.max_layers = args.carrier.max_mimo_layers; - dl_args.pdsch.max_prb = args.carrier.nof_prb; + dl_args.pdsch.max_layers = args.nof_tx_ports; + dl_args.pdsch.max_prb = args.nof_max_prb; dl_args.nof_tx_antennas = args.nof_tx_ports; - dl_args.nof_max_prb = args.carrier.nof_prb; + dl_args.nof_max_prb = args.nof_max_prb; // Initialise DL if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { @@ -66,18 +67,13 @@ bool slot_worker::init(const args_t& args) return false; } - // Set gNb DL carrier - if (srsran_gnb_dl_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) { - logger.error("Error setting DL carrier"); - return false; - } // Prepare UL arguments srsran_gnb_ul_args_t ul_args = {}; ul_args.pusch.measure_time = true; - ul_args.pusch.max_layers = args.carrier.max_mimo_layers; - ul_args.pusch.max_prb = args.carrier.nof_prb; - ul_args.nof_max_prb = args.carrier.nof_prb; + ul_args.pusch.max_layers = args.nof_rx_ports; + ul_args.pusch.max_prb = args.nof_max_prb; + ul_args.nof_max_prb = args.nof_max_prb; // Initialise UL if (srsran_gnb_ul_init(&gnb_ul, rx_buffer[0], &ul_args) < SRSRAN_SUCCESS) { @@ -85,12 +81,6 @@ bool slot_worker::init(const args_t& args) return false; } - // Set gNb UL carrier - if (srsran_gnb_ul_set_carrier(&gnb_ul, &args.carrier) < SRSRAN_SUCCESS) { - logger.error("Error setting UL carrier"); - return false; - } - return true; } @@ -157,7 +147,7 @@ bool slot_worker::work_ul() return false; } - // Decode PUCCH + // For each PUCCH... for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { stack_interface_phy_nr::pucch_info_t pucch_info = {}; pucch_info.uci_data.cfg = pucch.uci_cfg; @@ -188,7 +178,7 @@ bool slot_worker::work_ul() } } - // Decode PUSCH + // For each PUSCH... for (stack_interface_phy_nr::pusch_t& pusch : ul_sched.pusch) { // Get payload PDU stack_interface_phy_nr::pusch_info_t pusch_info = {}; @@ -197,7 +187,7 @@ bool slot_worker::work_ul() pusch_info.pusch_data.tb[0].payload = pusch.data[0]; pusch_info.pusch_data.tb[1].payload = pusch.data[1]; - // Decode PUCCH + // Decode PUSCH if (srsran_gnb_ul_get_pusch(&gnb_ul, &ul_slot_cfg, &pusch.sch, &pusch.sch.grant, &pusch_info.pusch_data) < SRSRAN_SUCCESS) { logger.error("Error getting PUSCH"); @@ -340,6 +330,27 @@ void slot_worker::work_imp() common.worker_end(this, true, tx_rf_buffer, tx_time, true); } +bool slot_worker::set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_) +{ + // Set gNb DL carrier + if (srsran_gnb_dl_set_carrier(&gnb_dl, &carrier) < SRSRAN_SUCCESS) { + logger.error("Error setting DL carrier"); + return false; + } + + // Set gNb UL carrier + if (srsran_gnb_ul_set_carrier(&gnb_ul, &carrier) < SRSRAN_SUCCESS) { + logger.error("Error setting UL carrier"); + return false; + } + + pdcch_cfg = pdcch_cfg_; + + // Update subframe length + sf_len = SRSRAN_SF_LEN_PRB_NR(carrier.nof_prb); + + return true; +} } // namespace nr -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index d0de0be3b..533557681 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -18,15 +18,23 @@ worker_pool::worker_pool(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::sink& log_sink_, uint32_t max_workers) : - pool(max_workers), common(common_), stack(stack_), log_sink(log_sink_) + pool(max_workers), + common(common_), + stack(stack_), + log_sink(log_sink_), + logger(srslog::fetch_basic_logger("PHY-NR", log_sink)), + prach_stack_adaptor(stack_) { // Do nothing } bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list) { - // Add workers to workers pool and start threads + // Configure logger srslog::basic_levels log_level = srslog::str_to_basic_level(args.log.phy_level); + logger.set_level(log_level); + + // Add workers to workers pool and start threads for (uint32_t i = 0; i < args.nof_phy_threads; i++) { auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log.id_preamble, i), log_sink); log.set_level(log_level); @@ -39,11 +47,10 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li slot_worker::args_t w_args = {}; uint32_t cell_index = 0; w_args.cell_index = cell_index; - w_args.carrier = cell_list[cell_index].carrier; + w_args.nof_max_prb = cell_list[cell_index].carrier.nof_prb; w_args.nof_tx_ports = cell_list[cell_index].carrier.max_mimo_layers; w_args.nof_rx_ports = cell_list[cell_index].carrier.max_mimo_layers; w_args.pusch_max_nof_iter = args.pusch_max_nof_iter; - w_args.pdcch_cfg = cell_list[cell_index].pdcch; if (not w->init(w_args)) { return false; @@ -55,12 +62,41 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li void worker_pool::start_worker(slot_worker* w) { + // Feed PRACH detection before start processing + prach.new_tti(0, current_tti, w->get_buffer_rx(0)); + + // Start actual worker pool.start_worker(w); } slot_worker* worker_pool::wait_worker(uint32_t tti) { - return (slot_worker*)pool.wait_worker(tti); + slot_worker* w = (slot_worker*)pool.wait_worker(tti); + + // Only if a worker was available + if (w != nullptr) { + srsran_carrier_nr_t carrier_; + srsran_pdcch_cfg_nr_t pdcch_cfg_; + + // Copy configuration + { + std::unique_lock lock(common_cfg_mutex); + carrier_ = carrier; + pdcch_cfg_ = pdcch_cfg; + } + + // Set worker configuration + if (not w->set_common_cfg(carrier_, pdcch_cfg_)) { + logger.error("Error setting common config"); + return nullptr; + } + } + + // Save current TTI + current_tti = tti; + + // Return worker + return w; } slot_worker* worker_pool::wait_worker_id(uint32_t id) @@ -71,7 +107,42 @@ slot_worker* worker_pool::wait_worker_id(uint32_t id) void worker_pool::stop() { pool.stop(); + prach.stop(); +} + +int worker_pool::set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common_cfg) +{ + // Best effort to convert NR carrier into LTE cell + srsran_cell_t cell = {}; + int ret = srsran_carrier_to_cell(&common_cfg.carrier, &cell); + if (ret < SRSRAN_SUCCESS) { + logger.error("Converting carrier to cell for PRACH (%d)", ret); + return SRSRAN_ERROR; + } + + // Best effort to set up NR-PRACH config reused for NR + srsran_prach_cfg_t prach_cfg = common_cfg.prach; + uint32_t lte_nr_prach_offset = (common_cfg.carrier.nof_prb - cell.nof_prb) / 2; + if (prach_cfg.freq_offset < lte_nr_prach_offset) { + logger.error("prach_cfg.freq_offset=%d is not compatible with LTE", prach_cfg.freq_offset); + return SRSRAN_ERROR; + } + prach_cfg.freq_offset -= lte_nr_prach_offset; + prach_cfg.is_nr = true; + + // Set the PRACH configuration + prach.init(0, cell, prach_cfg, &prach_stack_adaptor, logger, 0, 1); + prach.set_max_prach_offset_us(1000); + + // Save current configuration + { + std::unique_lock lock(common_cfg_mutex); + carrier = common_cfg.carrier; + pdcch_cfg = common_cfg.pdcch; + } + + return SRSRAN_SUCCESS; } } // namespace nr -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index d355f9fad..7716da3e8 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -198,4 +198,6 @@ int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interf return m_mac->pusch_info(slot_cfg, pusch_info); } +void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {} + } // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 5e8acf1ad..56b9cf1ed 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -89,114 +89,6 @@ void mac_nr::stop() void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) {} -// Fills both, DL_CONFIG.request and TX.request structs -void mac_nr::get_dl_config(const uint32_t tti, - phy_interface_stack_nr::dl_config_request_t& config_request, - phy_interface_stack_nr::tx_request_t& tx_request) -{ - // send MIB over BCH every 80ms - if (tti % 80 == 0) { - // try to read BCH PDU from RRC - if (rrc_h->read_pdu_bcch_bch(tti, bcch_bch_payload) == SRSRAN_SUCCESS) { - logger.info("Adding BCH in TTI=%d", tti); - tx_request.pdus[tx_request.nof_pdus].pbch.mib_present = true; - tx_request.pdus[tx_request.nof_pdus].data[0] = bcch_bch_payload->msg; - tx_request.pdus[tx_request.nof_pdus].length = bcch_bch_payload->N_bytes; - tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus; - tx_request.nof_pdus++; - - if (pcap) { - pcap->write_dl_bch(bcch_bch_payload->msg, bcch_bch_payload->N_bytes, 0xffff, 0, tti); - } - } else { - logger.error("Couldn't read BCH payload from RRC"); - } - } - - // Schedule SIBs - for (auto& sib : bcch_dlsch_payload) { - if (sib.payload->N_bytes > 0) { - if (tti % (sib.periodicity * 10) == 0) { - logger.info("Adding SIB %d in TTI=%d", sib.index, tti); - - tx_request.pdus[tx_request.nof_pdus].data[0] = sib.payload->msg; - tx_request.pdus[tx_request.nof_pdus].length = sib.payload->N_bytes; - tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus; - - if (pcap) { - pcap->write_dl_si_rnti_nr(sib.payload->msg, sib.payload->N_bytes, 0xffff, 0, tti); - } - - tx_request.nof_pdus++; - } - } - } - - // Add MAC padding if TTI is empty - if (tx_request.nof_pdus == 0) { - uint32_t buffer_index = tti % SRSRAN_FDD_NOF_HARQ; - - ue_tx_buffer.at(buffer_index)->clear(); - ue_tx_pdu.init_tx(ue_tx_buffer.at(buffer_index).get(), args.tb_size); - - // read RLC PDU - ue_rlc_buffer->clear(); - int pdu_len = rlc_h->read_pdu(args.rnti, 4, ue_rlc_buffer->msg, args.tb_size - 2); - - // Only create PDU if RLC has something to tx - if (pdu_len > 0) { - logger.info("Adding MAC PDU for RNTI=%d", args.rnti); - ue_rlc_buffer->N_bytes = pdu_len; - logger.info(ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes, "Read %d B from RLC", ue_rlc_buffer->N_bytes); - - // add to MAC PDU and pack - ue_tx_pdu.add_sdu(4, ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes); - ue_tx_pdu.pack(); - - logger.debug(ue_tx_buffer.at(buffer_index)->msg, - ue_tx_buffer.at(buffer_index)->N_bytes, - "Generated MAC PDU (%d B)", - ue_tx_buffer.at(buffer_index)->N_bytes); - - tx_request.pdus[tx_request.nof_pdus].data[0] = ue_tx_buffer.at(buffer_index)->msg; - tx_request.pdus[tx_request.nof_pdus].length = ue_tx_buffer.at(buffer_index)->N_bytes; - tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus; - - if (pcap) { - pcap->write_dl_crnti_nr(tx_request.pdus[tx_request.nof_pdus].data[0], - tx_request.pdus[tx_request.nof_pdus].length, - args.rnti, - buffer_index, - tti); - } - - tx_request.nof_pdus++; - } - } - - config_request.tti = tti; - tx_request.tti = tti; -} - -int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) -{ - phy_interface_stack_nr::dl_config_request_t config_request = {}; - phy_interface_stack_nr::tx_request_t tx_request = {}; - - // step MAC TTI - logger.set_context(slot_cfg.idx); - - get_dl_config(slot_cfg.idx, config_request, tx_request); - - // send DL_CONFIG.request - phy_h->dl_config_request(config_request); - - // send TX.request - phy_h->tx_request(tx_request); - - return SRSRAN_SUCCESS; -} - int mac_nr::rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& rx_data) { // push received PDU on queue @@ -270,6 +162,11 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg) return SRSRAN_SUCCESS; } +int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) +{ + return 0; +} + int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { return 0; @@ -286,5 +183,6 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph { return 0; } +void mac_nr::rach_detected(const mac_interface_phy_nr::rach_info_t& rach_info) {} } // namespace srsenb diff --git a/srsue/hdr/phy/nr/worker_pool.h b/srsue/hdr/phy/nr/worker_pool.h index 286bf8bc1..81d579ef8 100644 --- a/srsue/hdr/phy/nr/worker_pool.h +++ b/srsue/hdr/phy/nr/worker_pool.h @@ -20,7 +20,7 @@ namespace srsue { namespace nr { -class worker_pool +class worker_pool : public srsue::phy_interface_stack_nr { private: srslog::basic_logger& logger; @@ -37,12 +37,18 @@ public: sf_worker* wait_worker(uint32_t tti); void start_worker(sf_worker* w); void stop(); - void send_prach(uint32_t prach_occasion, uint32_t preamble_index, int preamble_received_target_power); - int set_ul_grant(std::array array, uint16_t rnti, srsran_rnti_type_t rnti_type); - bool set_config(const srsran::phy_cfg_nr_t& cfg); - bool has_valid_sr_resource(uint32_t sr_id); - void clear_pending_grants(); + void send_prach(const uint32_t prach_occasion, + const int preamble_index, + const float preamble_received_target_power, + const float ta_base_sec = 0.0f) override; + int set_ul_grant(std::array array, + uint16_t rnti, + srsran_rnti_type_t rnti_type) override; + bool set_config(const srsran::phy_cfg_nr_t& cfg) override; + bool has_valid_sr_resource(uint32_t sr_id) override; + void clear_pending_grants() override; void get_metrics(phy_metrics_t& m); + int tx_request(const tx_request_t& request) override; }; } // namespace nr diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index 99436f87c..8a6bf8030 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -90,6 +90,7 @@ void sf_worker::work_imp() if (prach_ptr != nullptr) { // PRACH is available, set buffer, transmit and return tx_buffer.set(0, prach_ptr); + tx_buffer.set_nof_samples(SRSRAN_SF_LEN_PRB_NR(phy_state.cfg.carrier.nof_prb)); // Notify MAC about PRACH transmission phy_state.stack->prach_sent(TTI_TX(tti_rx), diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 13cb11983..44e985784 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -91,7 +91,10 @@ void worker_pool::stop() pool.stop(); } -void worker_pool::send_prach(uint32_t prach_occasion, uint32_t preamble_index, int preamble_received_target_power) +void worker_pool::send_prach(const uint32_t prach_occasion, + const int preamble_index, + const float preamble_received_target_power, + const float ta_base_sec) { prach_buffer->prepare_to_send(preamble_index); } @@ -186,6 +189,10 @@ void worker_pool::get_metrics(phy_metrics_t& m) { phy_state.get_metrics(m); } +int worker_pool::tx_request(const phy_interface_mac_nr::tx_request_t& request) +{ + return 0; +} } // namespace nr } // namespace srsue diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 6176d5aa6..1a071a115 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -20,7 +20,11 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) - add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test --duration=100 --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" --gnb.stack.pusch.slots=\"\") + add_nr_test(nr_phy_test_10MHz_dl_only nr_phy_test + --duration=100 + --gnb.stack.pdsch.slots=\"0,1,2,3,4,5\" + --gnb.stack.pusch.slots=\"\") + add_nr_test(nr_phy_test_10MHz_ul_only nr_phy_test --duration=100 # 100 slots --gnb.stack.pdsch.slots=6 # No PDSCH @@ -29,6 +33,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS ) + add_nr_test(nr_phy_test_10MHz_bidir nr_phy_test --duration=100 # 100 slots --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots @@ -40,4 +45,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS ) + + add_nr_test(nr_phy_test_10MHz_prach nr_phy_test + --duration=1000 # 100 slots + --gnb.stack.pdsch.slots=6 # No PDSCH + --gnb.stack.pusch.slots=0 # No PUSCH + --ue.stack.prach.period=30 # Transmit PRACH every 30 radio frames + --ue.stack.prach.preamble=10 # Use preamble 10 + ) endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 1941beff4..3da1b293f 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -26,6 +26,17 @@ class gnb_dummy_stack : public srsenb::stack_interface_phy_nr { +public: + struct prach_metrics_t { + uint32_t count; + float avg_ta; + }; + + struct metrics_t { + std::map prach = {}; ///< PRACH metrics indexed with premable index + srsenb::mac_ue_metrics_t mac = {}; ///< MAC metrics + }; + private: srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); const uint16_t rnti = 0x1234; @@ -41,8 +52,8 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; - std::mutex mac_metrics_mutex; - srsenb::mac_ue_metrics_t mac_metrics = {}; + std::mutex metrics_mutex; + metrics_t metrics = {}; // HARQ feedback class pending_ack_t @@ -245,16 +256,16 @@ private: bool handle_uci_data(const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value) { - std::unique_lock lock(mac_metrics_mutex); + std::unique_lock lock(metrics_mutex); for (uint32_t i = 0; i < cfg.ack.count; i++) { const srsran_harq_ack_bit_t* ack_bit = &cfg.ack.bits[i]; bool is_ok = (value.ack[i] == 1) and value.valid; uint32_t tb_count = (ack_bit->tb0 ? 1 : 0) + (ack_bit->tb1 ? 1 : 0); - mac_metrics.tx_brate += tx_harq_proc[ack_bit->pid].get_tbs(); - mac_metrics.tx_pkts += tb_count; + metrics.mac.tx_brate += tx_harq_proc[ack_bit->pid].get_tbs(); + metrics.mac.tx_pkts += tb_count; if (not is_ok) { - mac_metrics.tx_errors += tb_count; + metrics.mac.tx_errors += tb_count; logger.debug("NACK received!"); } } @@ -452,19 +463,27 @@ public: } if (not pusch_info.pusch_data.tb[0].crc) { - mac_metrics.rx_errors++; + metrics.mac.rx_errors++; } - mac_metrics.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs(); - mac_metrics.rx_pkts++; + metrics.mac.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs(); + metrics.mac.rx_pkts++; return SRSRAN_SUCCESS; } - srsenb::mac_ue_metrics_t get_metrics() + void rach_detected(const rach_info_t& rach_info) override { - std::unique_lock lock(mac_metrics_mutex); + std::unique_lock lock(metrics_mutex); + prach_metrics_t& prach_metrics = metrics.prach[rach_info.preamble]; + prach_metrics.avg_ta = SRSRAN_VEC_SAFE_CMA((float)rach_info.time_adv, prach_metrics.avg_ta, prach_metrics.count); + prach_metrics.count++; + } - return mac_metrics; + metrics_t get_metrics() + { + std::unique_lock lock(metrics_mutex); + + return metrics; } }; diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index f2633e5c4..286960c3d 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -17,26 +17,60 @@ class ue_dummy_stack : public srsue::stack_interface_phy_nr { +public: + struct prach_metrics_t { + uint32_t count; + }; + + struct metrics_t { + std::map prach = {}; ///< PRACH metrics indexed with premable index + }; + private: - srsran_random_t random_gen = srsran_random_init(0x4567); - uint16_t rnti = 0; - bool valid = false; - uint32_t sr_period = 0; - uint32_t sr_count = 0; + srsran_random_t random_gen = srsran_random_init(0x4567); + uint16_t rnti = 0; + bool valid = false; + uint32_t sr_period = 0; + uint32_t sr_count = 0; + uint32_t prach_period = 0; + uint32_t prach_preamble = 0; + metrics_t metrics = {}; + srsue::phy_interface_stack_nr& phy; srsran::circular_array tx_harq_proc; srsran::circular_array rx_harq_proc; public: struct args_t { - uint16_t rnti = 0x1234; ///< C-RNTI for PUSCH and PDSCH transmissions - uint32_t sr_period = 0; ///< Indicates positive SR period in number of opportunities. Set to 0 to disable. + uint16_t rnti = 0x1234; ///< C-RNTI for PUSCH and PDSCH transmissions + uint32_t sr_period = 0; ///< Indicates positive SR period in number of opportunities. Set to 0 to disable. + uint32_t prach_period = 0; ///< Requests PHY to transmit PRACH periodically in frames. Set to 0 to disable. + uint32_t prach_preamble = 0; ///< Requests PHY to transmit PRACH periodically in frames. Set to 0 to disable. }; - ue_dummy_stack(const args_t& args) : rnti(args.rnti), sr_period(args.sr_period) { valid = true; } + ue_dummy_stack(const args_t& args, srsue::phy_interface_stack_nr& phy_) : + rnti(args.rnti), + sr_period(args.sr_period), + prach_period(args.prach_period), + prach_preamble(args.prach_preamble), + phy(phy_) + { + valid = true; + } ~ue_dummy_stack() { srsran_random_free(random_gen); } - void in_sync() override {} - void out_of_sync() override {} - void run_tti(const uint32_t tti) override {} + void in_sync() override {} + void out_of_sync() override {} + void run_tti(const uint32_t tti) override + { + // Run PRACH + if (prach_period != 0) { + uint32_t slot_idx = tti % SRSRAN_NSLOTS_PER_FRAME_NR(srsran_subcarrier_spacing_15kHz); + uint32_t sfn = tti / SRSRAN_NSLOTS_PER_FRAME_NR(srsran_subcarrier_spacing_15kHz); + if (slot_idx == 0 and sfn % prach_period == 0) { + phy.send_prach(0, prach_preamble, 0.0f, 0.0f); + metrics.prach[prach_preamble].count++; + } + } + } int sf_indication(const uint32_t tti) override { return 0; } sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) override { return {rnti, srsran_rnti_type_c}; } @@ -70,6 +104,8 @@ public: return ret; } bool is_valid() const { return valid; } + + metrics_t get_metrics() { return metrics; } }; #endif // SRSRAN_DUMMY_UE_STACK_H diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 2505a2645..2f2d25a77 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -72,7 +72,9 @@ test_bench::args_t::args_t(int argc, char** argv) ; options_ue_stack.add_options() - ("ue.stack.sr.period", bpo::value(&ue_stack.sr_period)->default_value(ue_stack.sr_period), "SR period in number of opportunities. Set 0 to disable and 1 for all.") + ("ue.stack.sr.period", bpo::value(&ue_stack.sr_period)->default_value(ue_stack.sr_period), "SR period in number of opportunities. Set 0 to disable and 1 for all.") + ("ue.stack.prach.period", bpo::value(&ue_stack.prach_period)->default_value(ue_stack.prach_period), "PRACH period in SFN. Set 0 to disable and 1 for all.") + ("ue.stack.prach.preamble", bpo::value(&ue_stack.prach_preamble)->default_value(ue_stack.prach_preamble), "PRACH preamble. Set 0 to disable and 1 for all.") ; options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options() @@ -153,18 +155,18 @@ int main(int argc, char** argv) srslog::flush(); // Retrieve MAC metrics - srsenb::mac_ue_metrics_t mac_metrics = tb.get_gnb_metrics(); + test_bench::metrics_t metrics = tb.get_gnb_metrics(); // Print PDSCH metrics if scheduled - if (mac_metrics.tx_pkts > 0) { + if (metrics.gnb_stack.mac.tx_pkts > 0) { float pdsch_bler = 0.0f; - pdsch_bler = (float)mac_metrics.tx_errors / (float)mac_metrics.tx_pkts; + pdsch_bler = (float)metrics.gnb_stack.mac.tx_errors / (float)metrics.gnb_stack.mac.tx_pkts; float pdsch_shed_rate = 0.0f; - pdsch_shed_rate = (float)mac_metrics.tx_brate / (float)mac_metrics.tx_pkts / 1000.0f; + pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f; srsran::console("PDSCH:\n"); - srsran::console(" Count: %d\n", mac_metrics.tx_pkts); + srsran::console(" Count: %d\n", metrics.gnb_stack.mac.tx_pkts); srsran::console(" BLER: %f\n", pdsch_bler); srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate); srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate); @@ -173,19 +175,19 @@ int main(int argc, char** argv) } // Print PUSCH metrics if scheduled - if (mac_metrics.rx_pkts > 0) { + if (metrics.gnb_stack.mac.rx_pkts > 0) { float pusch_bler = 0.0f; - if (mac_metrics.rx_pkts != 0) { - pusch_bler = (float)mac_metrics.rx_errors / (float)mac_metrics.rx_pkts; + if (metrics.gnb_stack.mac.rx_pkts != 0) { + pusch_bler = (float)metrics.gnb_stack.mac.rx_errors / (float)metrics.gnb_stack.mac.rx_pkts; } float pusch_shed_rate = 0.0f; - if (mac_metrics.rx_pkts != 0) { - pusch_shed_rate = (float)mac_metrics.rx_brate / (float)mac_metrics.rx_pkts / 1000.0f; + if (metrics.gnb_stack.mac.rx_pkts != 0) { + pusch_shed_rate = (float)metrics.gnb_stack.mac.rx_brate / (float)metrics.gnb_stack.mac.rx_pkts / 1000.0f; } srsran::console("PUSCH:\n"); - srsran::console(" Count: %d\n", mac_metrics.rx_pkts); + srsran::console(" Count: %d\n", metrics.gnb_stack.mac.rx_pkts); srsran::console(" BLER: %f\n", pusch_bler); srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate); srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate); @@ -193,9 +195,43 @@ int main(int argc, char** argv) srsran::console("\n"); } + // Print PRACH + if (metrics.ue_stack.prach.size() > 0) { + srsran::console("PRACH:\n"); + srsran::console(" UE transmitted:\n"); + srsran::console(" +------------+------------+\n"); + srsran::console(" | %10s | %10s |\n", "preamble", "count"); + srsran::console(" +------------+------------+\n"); + + for (const auto& p : metrics.ue_stack.prach) { + srsran::console(" | %10d | %10d |\n", p.first, p.second.count); + + // Ensure the detected count matches with transmission + TESTASSERT(metrics.gnb_stack.prach.count(p.first)); + TESTASSERT(metrics.gnb_stack.prach[p.first].count == p.second.count); + } + srsran::console(" +------------+------------+\n\n"); + + srsran::console(" GNB detected:\n"); + srsran::console(" +------------+------------+------------+\n"); + srsran::console(" | %10s | %10s | %10s |\n", "preamble", "count", "avg TA"); + srsran::console(" +------------+------------+------------+\n"); + + for (const auto& p : metrics.gnb_stack.prach) { + srsran::console(" | %10d | %10d | %10.1f |\n", p.first, p.second.count, p.second.avg_ta); + + // Ensure all detected preambles were transmitted + TESTASSERT(metrics.ue_stack.prach.count(p.first) > 0); + } + srsran::console(" +------------+------------+------------+\n\n"); + } else { + // In this case no PRACH should + TESTASSERT(metrics.gnb_stack.prach.empty()); + } + // Assert metrics - TESTASSERT(mac_metrics.tx_errors == 0); - TESTASSERT(mac_metrics.rx_errors == 0); + TESTASSERT(metrics.gnb_stack.mac.tx_errors == 0); + TESTASSERT(metrics.gnb_stack.mac.rx_errors == 0); // If reached here, the test is successful return SRSRAN_SUCCESS; diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index aa296dbe0..28cb5d907 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -24,7 +24,7 @@ private: const std::string GNB_PHY_COM_LOG_NAME = "GNB/PHY/COM"; uint32_t slot_idx = 0; uint64_t slot_count = 0; - uint64_t duration_slots; + uint64_t duration_slots = 0; gnb_dummy_stack gnb_stack; srsenb::nr::worker_pool gnb_phy; phy_common gnb_phy_com; @@ -53,10 +53,15 @@ public: args_t(int argc, char** argv); }; + struct metrics_t { + gnb_dummy_stack::metrics_t gnb_stack = {}; + ue_dummy_stack::metrics_t ue_stack = {}; + }; + test_bench(const args_t& args) : gnb_stack(args.gnb_stack), gnb_phy(gnb_phy_com, gnb_stack, srslog::get_default_sink(), args.gnb_phy.nof_phy_threads), - ue_stack(args.ue_stack), + ue_stack(args.ue_stack, ue_phy), ue_phy(args.ue_phy.nof_phy_threads), ue_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels), @@ -73,6 +78,15 @@ public: return; } + srsenb::phy_interface_rrc_nr::common_cfg_t common_cfg = {}; + common_cfg.carrier = args.phy_cfg.carrier; + common_cfg.pdcch = args.phy_cfg.pdcch; + common_cfg.prach = args.phy_cfg.prach; + + if (gnb_phy.set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { + return; + } + // Initialise UE PHY if (not ue_phy.init(args.ue_phy, ue_phy_com, &ue_stack, 31)) { return; @@ -147,7 +161,10 @@ public: ue_worker->set_tti(slot_idx); ue_worker->set_tx_time(ue_time); - // Start gNb work + // Run UE stack + ue_stack.run_tti(slot_idx); + + // Start UE work ue_phy_com.push_semaphore(ue_worker); ue_phy.start_worker(ue_worker); @@ -156,7 +173,13 @@ public: return slot_count <= duration_slots; } - srsenb::mac_ue_metrics_t get_gnb_metrics() { return gnb_stack.get_metrics(); } + metrics_t get_gnb_metrics() + { + metrics_t metrics = {}; + metrics.gnb_stack = gnb_stack.get_metrics(); + metrics.ue_stack = ue_stack.get_metrics(); + return metrics; + } }; #endif // SRSRAN_TEST_BENCH_H From 7b7ecb7983a715a98cc469c3b790c27dccd0daaa Mon Sep 17 00:00:00 2001 From: faluco Date: Tue, 13 Jul 2021 11:15:11 +0200 Subject: [PATCH 28/59] Add a new configuration option that controls PDSCH baseband sample dump to a file on KO. --- .../srsran/interfaces/ue_nr_interfaces.h | 1 + .../srsran/interfaces/ue_phy_interfaces.h | 6 +++-- srsue/src/main.cc | 5 ++++ srsue/src/phy/nr/cc_worker.cc | 27 +++++++++++++++++++ srsue/src/ue.cc | 1 + srsue/ue.conf.example | 9 +++++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index b59626a48..9d60ed1bb 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -175,6 +175,7 @@ struct phy_args_nr_t { srsran_ue_ul_nr_args_t ul = {}; std::set fixed_sr = {1}; uint32_t fix_wideband_cqi = 15; // Set to a non-zero value for fixing the wide-band CQI report + bool store_pdsch_ko = false; phy_args_nr_t() { diff --git a/lib/include/srsran/interfaces/ue_phy_interfaces.h b/lib/include/srsran/interfaces/ue_phy_interfaces.h index f628295db..0f2735f90 100644 --- a/lib/include/srsran/interfaces/ue_phy_interfaces.h +++ b/lib/include/srsran/interfaces/ue_phy_interfaces.h @@ -86,6 +86,8 @@ struct phy_args_t { float force_ul_amplitude = 0.0f; bool detect_cp = false; + bool nr_store_pdsch_ko = false; + float in_sync_rsrp_dbm_th = -130.0f; float in_sync_snr_db_th = 1.0f; uint32_t nof_in_sync_events = 10; @@ -129,8 +131,8 @@ public: } prach_info_t; virtual void - prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0; - virtual prach_info_t prach_get_info() = 0; + prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0; + virtual prach_info_t prach_get_info() = 0; /* Indicates the transmission of a SR signal in the next opportunity */ virtual void sr_send() = 0; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index f7c700bc2..666ba2c6c 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -405,6 +405,11 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) bpo::value(&args->phy.force_N_id_2)->default_value(-1), "Force using a specific PSS (set to -1 to allow all PSSs).") + // PHY NR args + ("phy.nr.store_pdsch_ko", + bpo::value(&args->phy.nr_store_pdsch_ko)->default_value(false), + "Dumps the PDSCH baseband samples into a file on KO reception.") + // UE simulation args ("sim.airplane_t_on_ms", bpo::value(&args->stack.nas.sim.airplane_t_on_ms)->default_value(-1), diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 6f69a5e2b..bbdea7910 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -13,6 +13,7 @@ #include "srsue/hdr/phy/nr/cc_worker.h" #include "srsran/common/band_helper.h" #include "srsran/common/buffer_pool.h" +#include "srsran/common/string_helpers.h" #include "srsran/srsran.h" namespace srsue { @@ -300,6 +301,32 @@ bool cc_worker::decode_pdsch_dl() } } + if (not pdsch_res.tb[0].crc and phy.args.store_pdsch_ko) { + static unsigned unique_filename_id = 0; + unsigned id = ++unique_filename_id; + + fmt::memory_buffer filename; + fmt::format_to(filename, "pdsch_ko_bb_samples_{}.bin", id); + + srsran_filesink_t filesink = {}; + if (srsran_filesink_init(&filesink, (char*)srsran::to_c_str(filename), SRSRAN_COMPLEX_FLOAT_BIN) == 0) { + srsran_filesink_write(&filesink, (void*)rx_buffer[0], ue_dl.fft[0].sf_sz); + srsran_filesink_free(&filesink); + + str_extra_t str_extra; + srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size()); + logger.info("PDSCH: KO detected, dumping PDSCH baseband samples into file '%s'" + "\n" + "Information: cc_idx=%d pid=%d slot_idx=%d sf_len=%d\n%s", + srsran::to_c_str(filename), + cc_idx, + pid, + dl_slot_cfg.idx, + ue_dl.fft[0].sf_sz, + str_extra.data()); + } + } + // Enqueue PDSCH ACK information only if the RNTI is type C if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { phy.set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res.tb[0].crc); diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 7b4d7cbd1..e5413776f 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -97,6 +97,7 @@ int ue::init(const all_args_t& args_) phy_args_nr.nof_phy_threads = args.phy.nof_phy_threads; phy_args_nr.worker_cpu_mask = args.phy.worker_cpu_mask; phy_args_nr.log = args.phy.log; + phy_args_nr.store_pdsch_ko = args.phy.nr_store_pdsch_ko; if (lte_phy->init(phy_args_nr, lte_stack.get(), lte_radio.get())) { srsran::console("Error initializing NR PHY.\n"); ret = SRSRAN_ERROR; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 0b868aaf5..73620dfed 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -374,6 +374,15 @@ enable = false #nof_in_sync_events = 10 #nof_out_of_sync_events = 20 +##################################################################### +# PHY NR specific configuration options +# +# store_pdsch_ko: Dumps the PDSCH baseband samples into a file on KO reception +# +##################################################################### +[phy.nr] +#store_pdsch_ko = false + ##################################################################### # Simulation configuration options # From d990db66f6caf022f65e78ca256b440a856f72d4 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 9 Jul 2021 21:03:02 +0200 Subject: [PATCH 29/59] Added syslog logger --- lib/include/srsran/srslog/shared_types.h | 12 +++ lib/include/srsran/srslog/srslog.h | 8 ++ lib/src/srslog/sinks/syslog_sink.h | 97 ++++++++++++++++++++++++ lib/src/srslog/srslog.cpp | 20 +++++ lib/test/srslog/CMakeLists.txt | 4 + lib/test/srslog/syslog_sink_test.cpp | 63 +++++++++++++++ 6 files changed, 204 insertions(+) create mode 100644 lib/src/srslog/sinks/syslog_sink.h create mode 100644 lib/test/srslog/syslog_sink_test.cpp diff --git a/lib/include/srsran/srslog/shared_types.h b/lib/include/srsran/srslog/shared_types.h index c508219ef..90aa8c6d0 100644 --- a/lib/include/srsran/srslog/shared_types.h +++ b/lib/include/srsran/srslog/shared_types.h @@ -31,6 +31,18 @@ enum class backend_priority very_high }; +/// syslog log local types +enum class syslog_local_type { + local0, + local1, + local2, + local3, + local4, + local5, + local6, + local7, +}; + } // namespace srslog #endif // SRSLOG_SHARED_TYPES_H diff --git a/lib/include/srsran/srslog/srslog.h b/lib/include/srsran/srslog/srslog.h index 632d38a91..b9af1f5bc 100644 --- a/lib/include/srsran/srslog/srslog.h +++ b/lib/include/srsran/srslog/srslog.h @@ -184,6 +184,14 @@ sink& fetch_file_sink(const std::string& path, size_t max_size = 0, std::unique_ptr f = get_default_log_formatter()); +/// Returns an instance of a sink that writes into syslog +/// preamble: The string prepended to every message, If ident is "", the program name is used. +/// log_local: custom unused facilities that syslog provides which can be used by the user +/// NOTE: Any '#' characters in the path will get removed. +sink& fetch_syslog_sink(const std::string& preamble_ = "", + syslog_local_type log_local_ = syslog_local_type::local0, + std::unique_ptr f = get_default_log_formatter()); + /// Installs a custom user defined sink in the framework getting associated to /// the specified id. Returns true on success, otherwise false. /// WARNING: This function is an advanced feature and users should really know diff --git a/lib/src/srslog/sinks/syslog_sink.h b/lib/src/srslog/sinks/syslog_sink.h new file mode 100644 index 000000000..2c0b8b02a --- /dev/null +++ b/lib/src/srslog/sinks/syslog_sink.h @@ -0,0 +1,97 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSLOG_SYSLOG_SINK_H +#define SRSLOG_SYSLOG_SINK_H + +#include "srsran/srslog/shared_types.h" +#include "srsran/srslog/sink.h" +#include + +namespace srslog { + +/// This sink implementation writes to syslog. +class syslog_sink : public sink +{ +public: + syslog_sink(std::unique_ptr f, + std::string preamble_ = "", + syslog_local_type log_local_ = syslog_local_type::local0) : + sink(std::move(f)) + { + create_syslog(preamble_, syslog_translate(log_local_)); + } + + syslog_sink(const syslog_sink& other) = delete; + syslog_sink& operator=(const syslog_sink& other) = delete; + + detail::error_string write(detail::memory_buffer buffer) override + { + std::string entry(buffer.data(), buffer.size()); + if (entry.find("[E]") != std::string::npos) { + syslog(LOG_ERR, "%s", buffer.data()); + } else if (entry.find("[W]") != std::string::npos) { + syslog(LOG_WARNING, "%s", buffer.data()); + } else if (entry.find("[I]") != std::string::npos) { + syslog(LOG_INFO, "%s", buffer.data()); + } else if (entry.find("[D]") != std::string::npos) { + syslog(LOG_DEBUG, "%s", buffer.data()); + } else { + syslog(LOG_ERR, "%s", buffer.data()); + } + // openlog syslog does not return any value. + return {}; + } + + detail::error_string flush() override { return {}; } + +private: + /// Creates a new syslog + detail::error_string create_syslog(std::string preamble, int log_local) + { + if (preamble == "") { + openlog(NULL, LOG_CONS | LOG_PID | LOG_NDELAY, log_local); + } else { + openlog(preamble.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, log_local); + } + return {}; + } + + static int syslog_translate(syslog_local_type log_local) + { + switch (log_local) { + case syslog_local_type::local0: + return LOG_LOCAL0; + case syslog_local_type::local1: + return LOG_LOCAL1; + case syslog_local_type::local2: + return LOG_LOCAL2; + case syslog_local_type::local3: + return LOG_LOCAL3; + case syslog_local_type::local4: + return LOG_LOCAL4; + case syslog_local_type::local5: + return LOG_LOCAL5; + case syslog_local_type::local6: + return LOG_LOCAL6; + case syslog_local_type::local7: + return LOG_LOCAL7; + default: + return LOG_LOCAL0; + break; + } + }; +}; + +} // namespace srslog + +#endif // SRSLOG_SYSLOG_SINK_H diff --git a/lib/src/srslog/srslog.cpp b/lib/src/srslog/srslog.cpp index b50e6c627..947cea375 100644 --- a/lib/src/srslog/srslog.cpp +++ b/lib/src/srslog/srslog.cpp @@ -13,6 +13,7 @@ #include "srsran/srslog/srslog.h" #include "formatters/json_formatter.h" #include "sinks/file_sink.h" +#include "sinks/syslog_sink.h" #include "srslog_instance.h" using namespace srslog; @@ -165,6 +166,25 @@ sink& srslog::fetch_file_sink(const std::string& path, size_t max_size, std::uni return *s; } +sink& srslog::fetch_syslog_sink(const std::string& preamble_, + syslog_local_type log_local_, + std::unique_ptr f) +{ + std::string sink_id = preamble_ + std::to_string(static_cast(log_local_)); + if (auto* s = find_sink(sink_id)) { + return *s; + } + + //: TODO: GCC5 or lower versions emits an error if we use the new() expression + // directly, use redundant piecewise_construct instead. + auto& s = srslog_instance::get().get_sink_repo().emplace( + std::piecewise_construct, + std::forward_as_tuple(sink_id), + std::forward_as_tuple(new syslog_sink(std::move(f), preamble_, log_local_))); + + return *s; +} + bool srslog::install_custom_sink(const std::string& id, std::unique_ptr s) { assert(!id.empty() && "Empty path string"); diff --git a/lib/test/srslog/CMakeLists.txt b/lib/test/srslog/CMakeLists.txt index 46a59303e..b875acfe0 100644 --- a/lib/test/srslog/CMakeLists.txt +++ b/lib/test/srslog/CMakeLists.txt @@ -35,6 +35,10 @@ target_include_directories(file_sink_test PUBLIC ../../) target_link_libraries(file_sink_test srslog) add_test(file_sink_test file_sink_test) +add_executable(syslog_sink_test syslog_sink_test.cpp) +target_include_directories(syslog_sink_test PUBLIC ../../) +target_link_libraries(syslog_sink_test srslog) + add_executable(file_utils_test file_utils_test.cpp) target_include_directories(file_utils_test PUBLIC ../../) target_link_libraries(file_utils_test srslog) diff --git a/lib/test/srslog/syslog_sink_test.cpp b/lib/test/srslog/syslog_sink_test.cpp new file mode 100644 index 000000000..51f958fb4 --- /dev/null +++ b/lib/test/srslog/syslog_sink_test.cpp @@ -0,0 +1,63 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "src/srslog/sinks/syslog_sink.h" +#include "srsran/srslog/srslog.h" +#include "test_dummies.h" +#include "testing_helpers.h" + +#include +#include + +using namespace srslog; + +/// Syslog sink name. +static constexpr char sink_name[] = "srslog_syslog_sink"; + +static bool find_string_infile(std::string filename, std::string pattern) +{ + std::ifstream file(filename); + std::string line; + bool found = false; + + if (file.is_open()) { + while (std::getline(file, line)) { + if (line.find(pattern) != std::string::npos) { // WILL SEARCH 2015-1113 in file + found = true; + } + } + } else { + printf("WARNING: Could not open file %s", filename.c_str()); + } + return found; +} + +static bool syslog_basic_test() +{ + syslog_sink syslog_sink(get_default_log_formatter()); + + // Build a 1000 byte entry. + std::string entry(1000, 'a'); + + syslog_sink.write(detail::memory_buffer(entry)); + + syslog_sink.flush(); + + ASSERT_EQ(find_string_infile("/var/log/syslog", entry), true); + return true; +} + +int main() +{ + TEST_FUNCTION(syslog_basic_test); + return 0; +} \ No newline at end of file From 1fd9d4300c019dac86a3aaddd6439c04cae86a39 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 14 Jul 2021 11:18:46 +0200 Subject: [PATCH 30/59] Move pdu buffer mutex in mac::ue to each carrier buffer map --- srsenb/hdr/stack/mac/ue.h | 2 +- srsenb/src/stack/mac/ue.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 3718771ad..8855d9a1b 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -81,6 +81,7 @@ public: private: srslog::basic_logger* logger; + std::mutex mutex; srsran::static_circular_map pdu_map; }; @@ -215,7 +216,6 @@ private: // Mutexes std::mutex mutex; - std::mutex rx_buffers_mutex; }; } // namespace srsenb diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index cae9939f2..791b08725 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -71,6 +71,7 @@ cc_used_buffers_map::~cc_used_buffers_map() srsran::unique_byte_buffer_t cc_used_buffers_map::release_pdu(tti_point tti) { + std::unique_lock lock(mutex); if (not has_tti(tti)) { return nullptr; } @@ -85,6 +86,7 @@ srsran::unique_byte_buffer_t cc_used_buffers_map::release_pdu(tti_point tti) uint8_t* cc_used_buffers_map::request_pdu(tti_point tti, uint32_t len) { + std::unique_lock lock(mutex); if (not pdu_map.has_space(tti.to_uint())) { logger->error("UE buffers: could not allocate buffer for tti=%d", tti.to_uint()); return nullptr; @@ -105,6 +107,7 @@ uint8_t* cc_used_buffers_map::request_pdu(tti_point tti, uint32_t len) void cc_used_buffers_map::clear_old_pdus(tti_point current_tti) { + std::unique_lock lock(mutex); static const uint32_t old_tti_threshold = SRSRAN_FDD_NOF_HARQ + 4; tti_point max_tti{current_tti - old_tti_threshold}; @@ -253,13 +256,11 @@ srsran_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq uint8_t* ue::request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len) { srsran_assert(len > 0, "UE buffers: Requesting buffer for zero bytes"); - std::unique_lock lock(rx_buffers_mutex); return cc_buffers[enb_cc_idx].get_rx_used_buffers().request_pdu(tti_point(tti), len); } void ue::clear_old_buffers(uint32_t tti) { - std::unique_lock lock(rx_buffers_mutex); // remove old buffers for (auto& cc : cc_buffers) { cc.get_rx_used_buffers().clear_old_pdus(tti_point{tti}); @@ -389,7 +390,6 @@ void ue::process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint3 srsran::unique_byte_buffer_t ue::release_pdu(uint32_t tti, uint32_t enb_cc_idx) { - std::lock_guard lock(rx_buffers_mutex); return cc_buffers[enb_cc_idx].get_rx_used_buffers().release_pdu(tti_point(tti)); } From 72cf3a1cecc350826c926741a88a738ea95fe048 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 27 May 2021 22:01:56 +0100 Subject: [PATCH 31/59] Added RLC SRB1 and SRB2 configuration ability. The configuration was added to drb.conf --- srsenb/drb.conf.example | 33 ++++++++++++++ srsenb/hdr/stack/rrc/rrc_config.h | 2 + srsenb/src/enb_cfg_parser.cc | 76 ++++++++++++++++++++++++++++++- srsenb/src/enb_cfg_parser.h | 12 +++++ srsenb/src/stack/rrc/rrc.cc | 10 ++++ srsenb/src/stack/rrc/rrc_ue.cc | 8 +++- 6 files changed, 139 insertions(+), 2 deletions(-) diff --git a/srsenb/drb.conf.example b/srsenb/drb.conf.example index 55a1a1491..6c1220ed6 100644 --- a/srsenb/drb.conf.example +++ b/srsenb/drb.conf.example @@ -1,5 +1,38 @@ // All times are in ms. Use -1 for infinity, where available +srb1_config = ( +{ + rlc_config = { + ul_am = { + t_poll_retx = 45; + poll_pdu = -1; + poll_byte = -1; + max_retx_thresh = 4; + }; + dl_am = { + t_reordering = 35; + t_status_prohibit = 0; + }; + }; +} +) + +srb2_config = ( +{ + rlc_config = { + ul_am = { + t_poll_retx = 45; + poll_pdu = -1; + poll_byte = -1; + max_retx_thresh = 4; + }; + dl_am = { + t_reordering = 35; + t_status_prohibit = 0; + }; + }; +} +) qci_config = ( diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index fb5e7ca5a..ce30a8e6e 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -62,6 +62,8 @@ struct rrc_cfg_t { uint32_t max_mac_dl_kos; uint32_t max_mac_ul_kos; uint32_t rlf_release_timer_ms; + asn1::rrc::rlc_cfg_c srb1_cfg; + asn1::rrc::rlc_cfg_c srb2_cfg; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 49dda24e2..adec87116 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -397,6 +397,69 @@ int phr_cnfg_parser::parse(libconfig::Setting& root) return 0; } +int field_srb::parse(libconfig::Setting& root) +{ + libconfig::Setting& q = root[0]; + + // Parse RLC AM section + rlc_cfg_c* rlc_cfg = &cfg; + if (q["rlc_config"].exists("ul_am") && q["rlc_config"].exists("dl_am")) { + rlc_cfg->set_am(); + } + + // RLC-UM Should not exist section + if (q["rlc_config"].exists("ul_um") || q["rlc_config"].exists("dl_um")) { + ERROR("Error SRBs must be AM."); + return -1; + } + + // Parse RLC-AM section + if (q["rlc_config"].exists("ul_am")) { + ul_am_rlc_s* am_rlc = &rlc_cfg->am().ul_am_rlc; + + field_asn1_enum_number t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx); + if (t_poll_retx.parse(q["rlc_config"]["ul_am"])) { + ERROR("Error can't find t_poll_retx in section ul_am"); + return -1; + } + + field_asn1_enum_number poll_pdu("poll_pdu", &am_rlc->poll_pdu); + if (poll_pdu.parse(q["rlc_config"]["ul_am"])) { + ERROR("Error can't find poll_pdu in section ul_am"); + return -1; + } + + field_asn1_enum_number poll_byte("poll_byte", &am_rlc->poll_byte); + if (poll_byte.parse(q["rlc_config"]["ul_am"])) { + ERROR("Error can't find poll_byte in section ul_am"); + return -1; + } + + field_asn1_enum_number max_retx_thresh("max_retx_thresh", &am_rlc->max_retx_thres); + if (max_retx_thresh.parse(q["rlc_config"]["ul_am"])) { + ERROR("Error can't find max_retx_thresh in section ul_am"); + return -1; + } + } + + if (q["rlc_config"].exists("dl_am")) { + dl_am_rlc_s* am_rlc = &rlc_cfg->am().dl_am_rlc; + + field_asn1_enum_number t_reordering("t_reordering", &am_rlc->t_reordering); + if (t_reordering.parse(q["rlc_config"]["dl_am"])) { + ERROR("Error can't find t_reordering in section dl_am"); + return -1; + } + + field_asn1_enum_number t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit); + if (t_status_prohibit.parse(q["rlc_config"]["dl_am"])) { + ERROR("Error can't find t_status_prohibit in section dl_am"); + return -1; + } + } + return 0; +} + int field_qci::parse(libconfig::Setting& root) { auto nof_qci = (uint32_t)root.getLength(); @@ -1664,9 +1727,20 @@ namespace drb_sections { int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) { + parser::section srb1("srb1_config"); + srb1.add_field(new field_srb(rrc_cfg_->srb1_cfg)); + parser::section srb2("srb2_config"); + srb1.add_field(new field_srb(rrc_cfg_->srb2_cfg)); parser::section qci("qci_config"); qci.add_field(new field_qci(rrc_cfg_->qci_cfg)); - return parser::parse_section(args_->enb_files.drb_config, &qci); + + // Run parser with two sections + parser p(args_->enb_files.drb_config); + p.add_section(&srb1); + p.add_section(&srb2); + p.add_section(&qci); + + return p.parse(); } } // namespace drb_sections diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index 007015e68..98f0265cb 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -146,6 +146,18 @@ private: uint32_t default_offset; }; +class field_srb final : public parser::field_itf +{ +public: + explicit field_srb(asn1::rrc::rlc_cfg_c& cfg_) : cfg(cfg_) {} + const char* get_name() override { return "field_srb"; } + + int parse(Setting& root) override; + +private: + asn1::rrc::rlc_cfg_c& cfg; +}; + class field_qci final : public parser::field_itf { public: diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index cd157ae3f..013941252 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -103,6 +103,16 @@ int32_t rrc::init(const rrc_cfg_t& cfg_, running = true; + if (logger.debug.enabled()) { + asn1::json_writer js{}; + cfg.srb1_cfg.to_json(js); + logger.debug("SRB1 configuration: %s", js.to_string().c_str()); + } + if (logger.debug.enabled()) { + asn1::json_writer js{}; + cfg.srb2_cfg.to_json(js); + logger.debug("SRB2 configuration: %s", js.to_string().c_str()); + } return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index a634bf5a6..9bd7eaac6 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1411,7 +1411,13 @@ void rrc::ue::apply_pdcp_drb_updates(const rr_cfg_ded_s& pending_rr_cfg) void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) { for (const srb_to_add_mod_s& srb : pending_rr_cfg.srb_to_add_mod_list) { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); + if (srb.srb_id == 1) { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb1_cfg)); + } else if (srb.srb_id == 2) { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb2_cfg)); + } else { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); + } } if (pending_rr_cfg.drb_to_release_list.size() > 0) { for (uint8_t drb_id : pending_rr_cfg.drb_to_release_list) { From e19df2aedbb4e5e2a066e73d259a88942a291ac4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 31 May 2021 17:19:51 +0100 Subject: [PATCH 32/59] Make sure that SRB configuration goes in RR config dedicated message. --- srsenb/src/enb_cfg_parser.cc | 2 +- srsenb/src/stack/rrc/ue_rr_cfg.cc | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index adec87116..01f3a4191 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1730,7 +1730,7 @@ int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) parser::section srb1("srb1_config"); srb1.add_field(new field_srb(rrc_cfg_->srb1_cfg)); parser::section srb2("srb2_config"); - srb1.add_field(new field_srb(rrc_cfg_->srb2_cfg)); + srb2.add_field(new field_srb(rrc_cfg_->srb2_cfg)); parser::section qci("qci_config"); qci.add_field(new field_qci(rrc_cfg_->qci_cfg)); diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index ec93d917e..b280b5076 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -33,7 +33,7 @@ namespace srsenb { * SRBs / DRBs *****************************/ -srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id) +srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id, const asn1::rrc::rlc_cfg_c& srb_cfg) { if (srb_id > 2 or srb_id == 0) { srslog::fetch_basic_logger("RRC").error("Invalid SRB id=%d", srb_id); @@ -45,20 +45,20 @@ srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id) srb_it->lc_ch_cfg_present = true; srb_it->lc_ch_cfg.set(srb_to_add_mod_s::lc_ch_cfg_c_::types_opts::default_value); srb_it->rlc_cfg_present = true; - srb_it->rlc_cfg.set(srb_to_add_mod_s::rlc_cfg_c_::types_opts::default_value); - + srb_it->rlc_cfg.set(srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value); + srb_it->rlc_cfg.explicit_value() = srb_cfg; return srb_it; } -void fill_srbs_reconf(srb_to_add_mod_list_l& srbs, const srb_to_add_mod_list_l& current_srbs) +void fill_srbs_reconf(srb_to_add_mod_list_l& srbs, const srb_to_add_mod_list_l& current_srbs, const rrc_cfg_t& enb_cfg) { // NOTE: In case of Handover, the Reconf includes SRB1 if (srsran::find_rrc_obj_id(current_srbs, 1) == current_srbs.end()) { - add_srb(srbs, 1); + add_srb(srbs, 1, enb_cfg.srb1_cfg); } if (srsran::find_rrc_obj_id(current_srbs, 2) == current_srbs.end()) { - add_srb(srbs, 2); + add_srb(srbs, 2, enb_cfg.srb2_cfg); } } @@ -299,7 +299,7 @@ void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, // (Re)establish SRB1 rr_cfg.srb_to_add_mod_list_present = true; - add_srb(rr_cfg.srb_to_add_mod_list, 1); + add_srb(rr_cfg.srb_to_add_mod_list, 1, enb_cfg.srb1_cfg); // Setup SR/CQI configs rr_cfg.phys_cfg_ded_present = true; @@ -315,7 +315,7 @@ void fill_rr_cfg_ded_reconf(asn1::rrc::rr_cfg_ded_s& rr_cfg, bool phy_cfg_updated) { // (Re)establish SRBs - fill_srbs_reconf(rr_cfg.srb_to_add_mod_list, current_rr_cfg.srb_to_add_mod_list); + fill_srbs_reconf(rr_cfg.srb_to_add_mod_list, current_rr_cfg.srb_to_add_mod_list, enb_cfg); rr_cfg.srb_to_add_mod_list_present = rr_cfg.srb_to_add_mod_list.size() > 0; // Update DRBs if required From 17c09dfd75cc809629654f15368906720fa2e543 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 31 May 2021 17:31:39 +0100 Subject: [PATCH 33/59] Changed enb_cfg_parcer.cc to use SRSRAN_ERROR instead of -1 for error returning. --- srsenb/src/enb_cfg_parser.cc | 114 +++++++++++++++++------------------ 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 01f3a4191..504322d25 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -73,7 +73,7 @@ int field_sched_info::parse(libconfig::Setting& root) for (uint32_t i = 0; i < data->sched_info_list.size(); i++) { if (not parse_enum_by_number(data->sched_info_list[i].si_periodicity, "si_periodicity", root[i])) { fprintf(stderr, "Missing field si_periodicity in sched_info=%d\n", i); - return -1; + return SRSRAN_ERROR; } if (root[i].exists("si_mapping_info")) { data->sched_info_list[i].sib_map_info.resize((uint32_t)root[i]["si_mapping_info"].getLength()); @@ -84,12 +84,12 @@ int field_sched_info::parse(libconfig::Setting& root) data->sched_info_list[i].sib_map_info[j].value = (sib_type_e::options)(sib_index - 3); } else { fprintf(stderr, "Invalid SIB index %d for si_mapping_info=%d in sched_info=%d\n", sib_index, j, i); - return -1; + return SRSRAN_ERROR; } } } else { fprintf(stderr, "Number of si_mapping_info values exceeds maximum (%d)\n", ASN1_RRC_MAX_SIB); - return -1; + return SRSRAN_ERROR; } } else { data->sched_info_list[i].sib_map_info.resize(0); @@ -105,13 +105,13 @@ int field_intra_neigh_cell_list::parse(libconfig::Setting& root) for (uint32_t i = 0; i < data->intra_freq_neigh_cell_list.size() && i < ASN1_RRC_MAX_CELL_INTRA; i++) { if (not parse_enum_by_number(data->intra_freq_neigh_cell_list[i].q_offset_cell, "q_offset_range", root[i])) { fprintf(stderr, "Missing field q_offset_range in neigh_cell=%d\n", i); - return -1; + return SRSRAN_ERROR; } int phys_cell_id = 0; if (!root[i].lookupValue("phys_cell_id", phys_cell_id)) { fprintf(stderr, "Missing field phys_cell_id in neigh_cell=%d\n", i); - return -1; + return SRSRAN_ERROR; } data->intra_freq_neigh_cell_list[i].pci = (uint16)phys_cell_id; } @@ -125,14 +125,14 @@ int field_intra_black_cell_list::parse(libconfig::Setting& root) for (uint32_t i = 0; i < data->intra_freq_black_cell_list.size() && i < ASN1_RRC_MAX_CELL_BLACK; i++) { if (not parse_enum_by_number(data->intra_freq_black_cell_list[i].range, "range", root[i])) { fprintf(stderr, "Missing field range in black_cell=%d\n", i); - return -1; + return SRSRAN_ERROR; } data->intra_freq_black_cell_list[i].range_present = true; int start = 0; if (!root[i].lookupValue("start", start)) { fprintf(stderr, "Missing field start in black_cell=%d\n", i); - return -1; + return SRSRAN_ERROR; } data->intra_freq_black_cell_list[i].start = (uint16)start; } @@ -145,7 +145,7 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root) data->carrier_freqs_info_list_present = data->carrier_freqs_info_list.size() > 0; if (data->carrier_freqs_info_list.size() > ASN1_RRC_MAX_GNFG) { ERROR("CarrierFreqsInfoGERAN cannot have more than %d entries", ASN1_RRC_MAX_GNFG); - return -1; + return SRSRAN_ERROR; } for (uint32_t i = 0; i < data->carrier_freqs_info_list.size(); i++) { int cell_resel_prio; @@ -164,27 +164,27 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root) "ncc_permitted", &data->carrier_freqs_info_list[i].common_info.ncc_permitted); if (ncc_permitted.parse(root[i])) { ERROR("Error parsing `ncc_permitted` in carrier_freqs_info_lsit=%d", i); - return -1; + return SRSRAN_ERROR; } int q_rx_lev_min = 0; if (!root[i].lookupValue("q_rx_lev_min", q_rx_lev_min)) { ERROR("Missing field `q_rx_lev_min` in carrier_freqs_info_list=%d", i); - return -1; + return SRSRAN_ERROR; } data->carrier_freqs_info_list[i].common_info.q_rx_lev_min = q_rx_lev_min; int thresh_x_high = 0; if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) { ERROR("Missing field `thresh_x_high` in carrier_freqs_info_list=%d", i); - return -1; + return SRSRAN_ERROR; } data->carrier_freqs_info_list[i].common_info.thresh_x_high = thresh_x_high; int thresh_x_low = 0; if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) { ERROR("Missing field `thresh_x_low` in carrier_freqs_info_list=%d", i); - return -1; + return SRSRAN_ERROR; } data->carrier_freqs_info_list[i].common_info.thresh_x_low = thresh_x_low; @@ -197,7 +197,7 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root) &data->carrier_freqs_info_list[i].carrier_freqs.band_ind); if (band_ind.parse(root[i])) { ERROR("Error parsing `band_ind` in carrier_freqs_info_list=%d", i); - return -1; + return SRSRAN_ERROR; } data->carrier_freqs_info_list[i].carrier_freqs.following_arfcns.set_explicit_list_of_arfcns(); @@ -213,12 +213,12 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root) exp_l[j] = (short unsigned int)arfcn; } else { fprintf(stderr, "Invalid ARFCN %d in for carrier_freqs_info_list=%d explicit_list_of_arfcns\n", i, j); - return -1; + return SRSRAN_ERROR; } } } else { fprintf(stderr, "Number of ARFCN in explicit_list_of_arfcns exceeds maximum (%d)\n", 31); - return -1; + return SRSRAN_ERROR; } } else { exp_l.resize(0); @@ -264,7 +264,7 @@ int mbsfn_sf_cfg_list_parser::parse(Setting& root) } if (len > 1) { fprintf(stderr, "Only mbsfnSubframeConfigListLengths of size 1 are supported\n"); - return -1; + return SRSRAN_ERROR; } *enabled = true; mbsfn_list->resize(len); @@ -306,53 +306,53 @@ int mbsfn_area_info_list_parser::parse(Setting& root) &mbsfn_item->non_mbsfn_region_len); if (fieldlen.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing non_mbsfn_region_length\n"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_str repeat( "mcch_repetition_period", &mbsfn_item->mcch_cfg_r9.mcch_repeat_period_r9); if (repeat.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing mcch_repetition_period\n"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_str mod( "mcch_modification_period", &mbsfn_item->mcch_cfg_r9.mcch_mod_period_r9); if (mod.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing mcch_modification_period\n"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_str sig("signalling_mcs", &mbsfn_item->mcch_cfg_r9.sig_mcs_r9); if (sig.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing signalling_mcs\n"); - return -1; + return SRSRAN_ERROR; } parser::field areaid("mbsfn_area_id", &mbsfn_item->mbsfn_area_id_r9); if (areaid.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing mbsfn_area_id\n"); - return -1; + return SRSRAN_ERROR; } parser::field notif_ind("notification_indicator", &mbsfn_item->notif_ind_r9); if (notif_ind.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing notification_indicator\n"); - return -1; + return SRSRAN_ERROR; } parser::field offset("mcch_offset", &mbsfn_item->mcch_cfg_r9.mcch_offset_r9); if (offset.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing mcch_offset\n"); - return -1; + return SRSRAN_ERROR; } field_asn1_bitstring_number, uint8_t> alloc_info("sf_alloc_info", &mbsfn_item->mcch_cfg_r9.sf_alloc_info_r9); if (alloc_info.parse(root["mbsfn_area_info_list"])) { fprintf(stderr, "Error parsing mbsfn_area_info_list\n"); - return -1; + return SRSRAN_ERROR; } return 0; @@ -386,13 +386,13 @@ int phr_cnfg_parser::parse(libconfig::Setting& root) mac_main_cfg_s::phr_cfg_c_::setup_s_& s = phr_cfg->setup(); if (not parse_enum_by_str(s.dl_pathloss_change, "dl_pathloss_change", root["phr_cnfg"])) { - return -1; + return SRSRAN_ERROR; } if (not parse_enum_by_number(s.periodic_phr_timer, "periodic_phr_timer", root["phr_cnfg"])) { - return -1; + return SRSRAN_ERROR; } if (not parse_enum_by_number(s.prohibit_phr_timer, "prohibit_phr_timer", root["phr_cnfg"])) { - return -1; + return SRSRAN_ERROR; } return 0; } @@ -410,7 +410,7 @@ int field_srb::parse(libconfig::Setting& root) // RLC-UM Should not exist section if (q["rlc_config"].exists("ul_um") || q["rlc_config"].exists("dl_um")) { ERROR("Error SRBs must be AM."); - return -1; + return SRSRAN_ERROR; } // Parse RLC-AM section @@ -420,25 +420,25 @@ int field_srb::parse(libconfig::Setting& root) field_asn1_enum_number t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx); if (t_poll_retx.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find t_poll_retx in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number poll_pdu("poll_pdu", &am_rlc->poll_pdu); if (poll_pdu.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find poll_pdu in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number poll_byte("poll_byte", &am_rlc->poll_byte); if (poll_byte.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find poll_byte in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number max_retx_thresh("max_retx_thresh", &am_rlc->max_retx_thres); if (max_retx_thresh.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find max_retx_thresh in section ul_am"); - return -1; + return SRSRAN_ERROR; } } @@ -448,13 +448,13 @@ int field_srb::parse(libconfig::Setting& root) field_asn1_enum_number t_reordering("t_reordering", &am_rlc->t_reordering); if (t_reordering.parse(q["rlc_config"]["dl_am"])) { ERROR("Error can't find t_reordering in section dl_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit); if (t_status_prohibit.parse(q["rlc_config"]["dl_am"])) { ERROR("Error can't find t_status_prohibit in section dl_am"); - return -1; + return SRSRAN_ERROR; } } return 0; @@ -472,7 +472,7 @@ int field_qci::parse(libconfig::Setting& root) // Parse PDCP section if (!q.exists("pdcp_config")) { fprintf(stderr, "Error section pdcp_config not found for qci=%d\n", qci); - return -1; + return SRSRAN_ERROR; } rrc_cfg_qci_t qcicfg; @@ -501,7 +501,7 @@ int field_qci::parse(libconfig::Setting& root) rlc_cfg->set_um_uni_dir_dl(); } else { fprintf(stderr, "Invalid combination of UL/DL UM/AM for qci=%d\n", qci); - return -1; + return SRSRAN_ERROR; } // Parse RLC-UM section @@ -516,7 +516,7 @@ int field_qci::parse(libconfig::Setting& root) field_asn1_enum_number sn_field_len("sn_field_length", &um_rlc->sn_field_len); if (sn_field_len.parse(q["rlc_config"]["ul_um"])) { ERROR("Error can't find sn_field_length in section ul_um"); - return -1; + return SRSRAN_ERROR; } } @@ -531,13 +531,13 @@ int field_qci::parse(libconfig::Setting& root) field_asn1_enum_number sn_field_len("sn_field_length", &um_rlc->sn_field_len); if (sn_field_len.parse(q["rlc_config"]["dl_um"])) { ERROR("Error can't find sn_field_length in section dl_um"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number t_reordering("t_reordering", &um_rlc->t_reordering); if (t_reordering.parse(q["rlc_config"]["dl_um"])) { ERROR("Error can't find t_reordering in section dl_um"); - return -1; + return SRSRAN_ERROR; } } @@ -548,26 +548,26 @@ int field_qci::parse(libconfig::Setting& root) field_asn1_enum_number t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx); if (t_poll_retx.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find t_poll_retx in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number poll_pdu("poll_pdu", &am_rlc->poll_pdu); if (poll_pdu.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find poll_pdu in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number poll_byte("poll_byte", &am_rlc->poll_byte); if (poll_byte.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find poll_byte in section ul_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number max_retx_thresh("max_retx_thresh", &am_rlc->max_retx_thres); if (max_retx_thresh.parse(q["rlc_config"]["ul_am"])) { ERROR("Error can't find max_retx_thresh in section ul_am"); - return -1; + return SRSRAN_ERROR; } } @@ -577,20 +577,20 @@ int field_qci::parse(libconfig::Setting& root) field_asn1_enum_number t_reordering("t_reordering", &am_rlc->t_reordering); if (t_reordering.parse(q["rlc_config"]["dl_am"])) { ERROR("Error can't find t_reordering in section dl_am"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit); if (t_status_prohibit.parse(q["rlc_config"]["dl_am"])) { ERROR("Error can't find t_status_prohibit in section dl_am"); - return -1; + return SRSRAN_ERROR; } } // Parse logical channel configuration section if (!q.exists("logical_channel_config")) { fprintf(stderr, "Error section logical_channel_config not found for qci=%d\n", qci); - return -1; + return SRSRAN_ERROR; } lc_ch_cfg_s::ul_specific_params_s_* lc_cfg = &qcicfg.lc_cfg; @@ -598,21 +598,21 @@ int field_qci::parse(libconfig::Setting& root) parser::field priority("priority", &lc_cfg->prio); if (priority.parse(q["logical_channel_config"])) { ERROR("Error can't find logical_channel_config in section priority"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number prioritised_bit_rate( "prioritized_bit_rate", &lc_cfg->prioritised_bit_rate); if (prioritised_bit_rate.parse(q["logical_channel_config"])) { fprintf(stderr, "Error can't find prioritized_bit_rate in section logical_channel_config\n"); - return -1; + return SRSRAN_ERROR; } field_asn1_enum_number bucket_size_duration( "bucket_size_duration", &lc_cfg->bucket_size_dur); if (bucket_size_duration.parse(q["logical_channel_config"])) { ERROR("Error can't find bucket_size_duration in section logical_channel_config"); - return -1; + return SRSRAN_ERROR; } parser::field log_chan_group("log_chan_group", &lc_cfg->lc_ch_group); @@ -843,7 +843,7 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) HANDLEPARSERCODE(parse_meas_cell_list(&cell_cfg.meas_cfg, cellroot["meas_cell_list"])); if (not cellroot.exists("meas_report_desc")) { ERROR("PARSER ERROR: \"ho_active\" is set to true, but field \"meas_report_desc\" doesn't exist.\n"); - return -1; + return SRSRAN_ERROR; } HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot["meas_report_desc"])); } @@ -869,13 +869,13 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) // Check RF port is not repeated if (it->rf_port == it2->rf_port) { ERROR("Repeated RF port for multiple cells"); - return -1; + return SRSRAN_ERROR; } // Check cell ID is not repeated if (it->cell_id == it2->cell_id) { ERROR("Repeated Cell identifier"); - return -1; + return SRSRAN_ERROR; } } } @@ -1589,7 +1589,7 @@ int parse_sib9(std::string filename, sib_type9_s* data) } return 0; } else { - return -1; + return SRSRAN_ERROR; } } @@ -1635,19 +1635,19 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co std::string mnc_str; if (not srsran::mnc_to_string(args_->stack.s1ap.mnc, &mnc_str)) { ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mnc); - return -1; + return SRSRAN_ERROR; } std::string mcc_str; if (not srsran::mcc_to_string(args_->stack.s1ap.mcc, &mcc_str)) { ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mcc); - return -1; + return SRSRAN_ERROR; } sib_type1_s::cell_access_related_info_s_* cell_access = &sib1->cell_access_related_info; cell_access->plmn_id_list.resize(1); srsran::plmn_id_t plmn; if (plmn.from_string(mcc_str + mnc_str) == SRSRAN_ERROR) { ERROR("Could not convert %s to a plmn_id", (mcc_str + mnc_str).c_str()); - return -1; + return SRSRAN_ERROR; } srsran::to_asn1(&cell_access->plmn_id_list[0].plmn_id, plmn); cell_access->plmn_id_list[0].cell_reserved_for_oper = plmn_id_info_s::cell_reserved_for_oper_e_::not_reserved; @@ -1673,7 +1673,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co // verify SIB13 is available if (not sib_is_present(sib1->sched_info_list, sib_type_e::sib_type13_v920)) { fprintf(stderr, "SIB13 not present in sched_info.\n"); - return -1; + return SRSRAN_ERROR; } } From f0a28ebc88ea49ddc3621c220960032253fb1af7 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 31 May 2021 18:10:25 +0100 Subject: [PATCH 34/59] Rename drb.conf to rb.conf to reflect the now configurable SRBs. --- cmake/modules/SRSRAN_install_configs.sh.in | 2 +- srsenb/CMakeLists.txt | 6 +++--- srsenb/enb.conf.example | 4 ++-- srsenb/hdr/enb.h | 2 +- srsenb/{drb.conf.example => rb.conf.example} | 0 srsenb/src/enb_cfg_parser.cc | 2 +- srsenb/src/main.cc | 6 +++--- srsenb/test/rrc/test_helpers.cc | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) rename srsenb/{drb.conf.example => rb.conf.example} (100%) diff --git a/cmake/modules/SRSRAN_install_configs.sh.in b/cmake/modules/SRSRAN_install_configs.sh.in index aaa642cad..314b25f3b 100755 --- a/cmake/modules/SRSRAN_install_configs.sh.in +++ b/cmake/modules/SRSRAN_install_configs.sh.in @@ -105,7 +105,7 @@ install_file "ue.conf.example" install_file "enb.conf.example" install_file "sib.conf.example" install_file "rr.conf.example" -install_file "drb.conf.example" +install_file "rb.conf.example" install_file "epc.conf.example" install_file "mbms.conf.example" install_file "user_db.csv.example" diff --git a/srsenb/CMakeLists.txt b/srsenb/CMakeLists.txt index 2a65533f0..367e16db5 100644 --- a/srsenb/CMakeLists.txt +++ b/srsenb/CMakeLists.txt @@ -41,6 +41,6 @@ add_subdirectory(test) # Default configuration files ######################################################################## install(FILES enb.conf.example DESTINATION ${DATA_DIR}) -install(FILES drb.conf.example DESTINATION ${DATA_DIR}) -install(FILES rr.conf.example DESTINATION ${DATA_DIR}) -install(FILES sib.conf.example DESTINATION ${DATA_DIR}) \ No newline at end of file +install(FILES rb.conf.example DESTINATION ${DATA_DIR}) +install(FILES rr.conf.example DESTINATION ${DATA_DIR}) +install(FILES sib.conf.example DESTINATION ${DATA_DIR}) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index f7760089d..f0f004b07 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -36,12 +36,12 @@ n_prb = 50 # sib_config: SIB1, SIB2 and SIB3 configuration file # note: when enabling mbms, use the sib.conf.mbsfn configuration file which includes SIB13 # rr_config: Radio Resources configuration file -# drb_config: DRB configuration file +# rb_config: SRB/DRB configuration file ##################################################################### [enb_files] sib_config = sib.conf rr_config = rr.conf -drb_config = drb.conf +rb_config = rb.conf ##################################################################### # RF configuration diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index e3ccfca0b..1974b3901 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -62,7 +62,7 @@ struct enb_args_t { struct enb_files_t { std::string sib_config; std::string rr_config; - std::string drb_config; + std::string rb_config; }; struct log_args_t { diff --git a/srsenb/drb.conf.example b/srsenb/rb.conf.example similarity index 100% rename from srsenb/drb.conf.example rename to srsenb/rb.conf.example diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 504322d25..26c820324 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1735,7 +1735,7 @@ int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) qci.add_field(new field_qci(rrc_cfg_->qci_cfg)); // Run parser with two sections - parser p(args_->enb_files.drb_config); + parser p(args_->enb_files.rb_config); p.add_section(&srb1); p.add_section(&srb2); p.add_section(&qci); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index ba9c58477..6bb6aa002 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -83,7 +83,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("enb_files.sib_config", bpo::value(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files") ("enb_files.rr_config", bpo::value(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files") - ("enb_files.drb_config", bpo::value(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files") + ("enb_files.rb_config", bpo::value(&args->enb_files.rb_config)->default_value("rb.conf"), "SRB/DRB configuration files") ("rf.dl_earfcn", bpo::value(&args->enb.dl_earfcn)->default_value(0), "Force Downlink EARFCN for single cell") ("rf.srate", bpo::value(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz") @@ -436,8 +436,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) exit(1); } - if (!config_exists(args->enb_files.drb_config, "drb.conf")) { - cout << "Failed to read DRB configuration file " << args->enb_files.drb_config << " - exiting" << endl; + if (!config_exists(args->enb_files.rb_config, "rb.conf")) { + cout << "Failed to read DRB configuration file " << args->enb_files.rb_config << " - exiting" << endl; exit(1); } diff --git a/srsenb/test/rrc/test_helpers.cc b/srsenb/test/rrc/test_helpers.cc index 10b69e6bd..416fcf193 100644 --- a/srsenb/test/rrc/test_helpers.cc +++ b/srsenb/test/rrc/test_helpers.cc @@ -28,7 +28,7 @@ int parse_default_cfg_phy(rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_cfg, srsenb::all_ar *rrc_cfg = {}; args.enb_files.sib_config = argparse::repository_dir + "/sib.conf.example"; args.enb_files.rr_config = argparse::repository_dir + "/rr.conf.example"; - args.enb_files.drb_config = argparse::repository_dir + "/drb.conf.example"; + args.enb_files.rb_config = argparse::repository_dir + "/rb.conf.example"; srslog::fetch_basic_logger("TEST").debug("sib file path=%s", args.enb_files.sib_config.c_str()); args.enb.enb_id = 0x19B; @@ -48,7 +48,7 @@ int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) *rrc_cfg = {}; args.enb_files.sib_config = argparse::repository_dir + "/sib.conf.example"; args.enb_files.rr_config = argparse::repository_dir + "/rr.conf.example"; - args.enb_files.drb_config = argparse::repository_dir + "/drb.conf.example"; + args.enb_files.rb_config = argparse::repository_dir + "/rb.conf.example"; srslog::fetch_basic_logger("TEST").debug("sib file path=%s", args.enb_files.sib_config.c_str()); args.enb.enb_id = 0x19B; @@ -184,4 +184,4 @@ bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cel return cfg.pci == cell.pci and cell.cell_individual_offset.to_number() == (int8_t)round(cfg.q_offset); } -} // namespace srsenb \ No newline at end of file +} // namespace srsenb From 8d41c0d4764d0b1816bb1bb93e08dd083661afda Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 2 Jun 2021 18:05:21 +0100 Subject: [PATCH 35/59] Maded SRB configuration optional in rb.conf --- lib/src/asn1/rrc_utils.cc | 4 +++- srsenb/hdr/stack/rrc/rrc_config.h | 4 ++-- srsenb/src/enb_cfg_parser.cc | 18 ++++++++++++++++-- srsenb/src/enb_cfg_parser.h | 4 ++-- srsenb/src/stack/rrc/rrc.cc | 25 +++++++++++++++++-------- srsenb/src/stack/rrc/rrc_ue.cc | 12 ++++++++++-- srsenb/src/stack/rrc/ue_rr_cfg.cc | 6 +++--- 7 files changed, 53 insertions(+), 20 deletions(-) diff --git a/lib/src/asn1/rrc_utils.cc b/lib/src/asn1/rrc_utils.cc index f5a0ca8cc..73524624b 100644 --- a/lib/src/asn1/rrc_utils.cc +++ b/lib/src/asn1/rrc_utils.cc @@ -132,7 +132,9 @@ srsran::rlc_config_t make_rlc_config_t(const asn1::rrc::rlc_cfg_c& asn1_type) rlc_cfg.rlc_mode = rlc_mode_t::am; rlc_cfg.am.t_poll_retx = asn1_type.am().ul_am_rlc.t_poll_retx.to_number(); rlc_cfg.am.poll_pdu = asn1_type.am().ul_am_rlc.poll_pdu.to_number(); - rlc_cfg.am.poll_byte = asn1_type.am().ul_am_rlc.poll_byte.to_number() * 1000; // KB + rlc_cfg.am.poll_byte = asn1_type.am().ul_am_rlc.poll_byte.to_number() < 0 + ? -1 + : asn1_type.am().ul_am_rlc.poll_byte.to_number() * 1000; // KB rlc_cfg.am.max_retx_thresh = asn1_type.am().ul_am_rlc.max_retx_thres.to_number(); rlc_cfg.am.t_reordering = asn1_type.am().dl_am_rlc.t_reordering.to_number(); rlc_cfg.am.t_status_prohibit = asn1_type.am().dl_am_rlc.t_status_prohibit.to_number(); diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index ce30a8e6e..55a5e83c0 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -62,8 +62,8 @@ struct rrc_cfg_t { uint32_t max_mac_dl_kos; uint32_t max_mac_ul_kos; uint32_t rlf_release_timer_ms; - asn1::rrc::rlc_cfg_c srb1_cfg; - asn1::rrc::rlc_cfg_c srb2_cfg; + asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ srb1_cfg; + asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ srb2_cfg; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 26c820324..5f517a478 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -402,7 +402,7 @@ int field_srb::parse(libconfig::Setting& root) libconfig::Setting& q = root[0]; // Parse RLC AM section - rlc_cfg_c* rlc_cfg = &cfg; + rlc_cfg_c* rlc_cfg = &cfg.set_explicit_value(); if (q["rlc_config"].exists("ul_am") && q["rlc_config"].exists("dl_am")) { rlc_cfg->set_am(); } @@ -1728,9 +1728,15 @@ namespace drb_sections { int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) { parser::section srb1("srb1_config"); + bool srb1_present = false; + srb1.set_optional(&srb1_present); srb1.add_field(new field_srb(rrc_cfg_->srb1_cfg)); + parser::section srb2("srb2_config"); + bool srb2_present = false; + srb2.set_optional(&srb2_present); srb2.add_field(new field_srb(rrc_cfg_->srb2_cfg)); + parser::section qci("qci_config"); qci.add_field(new field_qci(rrc_cfg_->qci_cfg)); @@ -1740,7 +1746,15 @@ int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) p.add_section(&srb2); p.add_section(&qci); - return p.parse(); + int ret = p.parse(); + if (not srb1_present) { + rrc_cfg_->srb1_cfg.set_default_value(); + } + if (not srb2_present) { + rrc_cfg_->srb2_cfg.set_default_value(); + } + + return ret; } } // namespace drb_sections diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index 98f0265cb..2e1b0301c 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -149,13 +149,13 @@ private: class field_srb final : public parser::field_itf { public: - explicit field_srb(asn1::rrc::rlc_cfg_c& cfg_) : cfg(cfg_) {} + explicit field_srb(asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_& cfg_) : cfg(cfg_) {} const char* get_name() override { return "field_srb"; } int parse(Setting& root) override; private: - asn1::rrc::rlc_cfg_c& cfg; + asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_& cfg; }; class field_qci final : public parser::field_itf diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 013941252..b0d7a69b4 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -103,15 +103,24 @@ int32_t rrc::init(const rrc_cfg_t& cfg_, running = true; - if (logger.debug.enabled()) { - asn1::json_writer js{}; - cfg.srb1_cfg.to_json(js); - logger.debug("SRB1 configuration: %s", js.to_string().c_str()); + if (cfg.srb1_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value) { + if (logger.debug.enabled()) { + asn1::json_writer js{}; + cfg.srb1_cfg.to_json(js); + logger.debug("SRB1 explicit configuration: %s", js.to_string().c_str()); + } + } else { + logger.debug("SRB1 default configuration"); } - if (logger.debug.enabled()) { - asn1::json_writer js{}; - cfg.srb2_cfg.to_json(js); - logger.debug("SRB2 configuration: %s", js.to_string().c_str()); + + if (cfg.srb2_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value) { + if (logger.debug.enabled()) { + asn1::json_writer js{}; + cfg.srb2_cfg.to_json(js); + logger.debug("SRB2 configuration: %s", js.to_string().c_str()); + } + } else { + logger.debug("SRB2 default configuration"); } return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 9bd7eaac6..77f2aa2aa 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1412,9 +1412,17 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) { for (const srb_to_add_mod_s& srb : pending_rr_cfg.srb_to_add_mod_list) { if (srb.srb_id == 1) { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb1_cfg)); + if (parent->cfg.srb1_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb1_cfg.explicit_value())); + } else { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); + } } else if (srb.srb_id == 2) { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb2_cfg)); + if (parent->cfg.srb2_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb2_cfg.explicit_value())); + } else { + parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); + } } else { parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); } diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index b280b5076..7b7963a1c 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -33,7 +33,8 @@ namespace srsenb { * SRBs / DRBs *****************************/ -srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id, const asn1::rrc::rlc_cfg_c& srb_cfg) +srb_to_add_mod_s* +add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id, const asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_& srb_cfg) { if (srb_id > 2 or srb_id == 0) { srslog::fetch_basic_logger("RRC").error("Invalid SRB id=%d", srb_id); @@ -45,8 +46,7 @@ srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id, const asn srb_it->lc_ch_cfg_present = true; srb_it->lc_ch_cfg.set(srb_to_add_mod_s::lc_ch_cfg_c_::types_opts::default_value); srb_it->rlc_cfg_present = true; - srb_it->rlc_cfg.set(srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value); - srb_it->rlc_cfg.explicit_value() = srb_cfg; + srb_it->rlc_cfg = srb_cfg; return srb_it; } From e946cbd5de4fa2fe6565a5a667d6a9b3302b9369 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 4 Jun 2021 15:29:10 +0100 Subject: [PATCH 36/59] Tweaked SRB parsing to remove unecessary parenthisis --- srsenb/rb.conf.example | 62 +++++++++++++++++------------------- srsenb/src/enb_cfg_parser.cc | 32 +++++++++++-------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/srsenb/rb.conf.example b/srsenb/rb.conf.example index 6c1220ed6..c1d5b813a 100644 --- a/srsenb/rb.conf.example +++ b/srsenb/rb.conf.example @@ -1,38 +1,34 @@ - // All times are in ms. Use -1 for infinity, where available -srb1_config = ( -{ - rlc_config = { - ul_am = { - t_poll_retx = 45; - poll_pdu = -1; - poll_byte = -1; - max_retx_thresh = 4; - }; - dl_am = { - t_reordering = 35; - t_status_prohibit = 0; - }; - }; -} -) -srb2_config = ( -{ - rlc_config = { - ul_am = { - t_poll_retx = 45; - poll_pdu = -1; - poll_byte = -1; - max_retx_thresh = 4; - }; - dl_am = { - t_reordering = 35; - t_status_prohibit = 0; - }; - }; -} -) +// srb1_config = { +// rlc_config = { +// ul_am = { +// t_poll_retx = 45; +// poll_pdu = -1; +// poll_byte = -1; +// max_retx_thresh = 4; +// }; +// dl_am = { +// t_reordering = 35; +// t_status_prohibit = 0; +// }; +// }; +// } + +// srb2_config = { +// rlc_config = { +// ul_am = { +// t_poll_retx = 45; +// poll_pdu = -1; +// poll_byte = -1; +// max_retx_thresh = 4; +// }; +// dl_am = { +// t_reordering = 35; +// t_status_prohibit = 0; +// }; +// }; +// } qci_config = ( diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 5f517a478..a0a0084fd 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -399,60 +399,58 @@ int phr_cnfg_parser::parse(libconfig::Setting& root) int field_srb::parse(libconfig::Setting& root) { - libconfig::Setting& q = root[0]; - // Parse RLC AM section rlc_cfg_c* rlc_cfg = &cfg.set_explicit_value(); - if (q["rlc_config"].exists("ul_am") && q["rlc_config"].exists("dl_am")) { + if (root.exists("ul_am") && root.exists("dl_am")) { rlc_cfg->set_am(); } // RLC-UM Should not exist section - if (q["rlc_config"].exists("ul_um") || q["rlc_config"].exists("dl_um")) { + if (root.exists("ul_um") || root.exists("dl_um")) { ERROR("Error SRBs must be AM."); return SRSRAN_ERROR; } // Parse RLC-AM section - if (q["rlc_config"].exists("ul_am")) { + if (root.exists("ul_am")) { ul_am_rlc_s* am_rlc = &rlc_cfg->am().ul_am_rlc; field_asn1_enum_number t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx); - if (t_poll_retx.parse(q["rlc_config"]["ul_am"])) { + if (t_poll_retx.parse(root["ul_am"])) { ERROR("Error can't find t_poll_retx in section ul_am"); return SRSRAN_ERROR; } field_asn1_enum_number poll_pdu("poll_pdu", &am_rlc->poll_pdu); - if (poll_pdu.parse(q["rlc_config"]["ul_am"])) { + if (poll_pdu.parse(root["ul_am"])) { ERROR("Error can't find poll_pdu in section ul_am"); return SRSRAN_ERROR; } field_asn1_enum_number poll_byte("poll_byte", &am_rlc->poll_byte); - if (poll_byte.parse(q["rlc_config"]["ul_am"])) { + if (poll_byte.parse(root["ul_am"])) { ERROR("Error can't find poll_byte in section ul_am"); return SRSRAN_ERROR; } field_asn1_enum_number max_retx_thresh("max_retx_thresh", &am_rlc->max_retx_thres); - if (max_retx_thresh.parse(q["rlc_config"]["ul_am"])) { + if (max_retx_thresh.parse(root["ul_am"])) { ERROR("Error can't find max_retx_thresh in section ul_am"); return SRSRAN_ERROR; } } - if (q["rlc_config"].exists("dl_am")) { + if (root.exists("dl_am")) { dl_am_rlc_s* am_rlc = &rlc_cfg->am().dl_am_rlc; field_asn1_enum_number t_reordering("t_reordering", &am_rlc->t_reordering); - if (t_reordering.parse(q["rlc_config"]["dl_am"])) { + if (t_reordering.parse(root["dl_am"])) { ERROR("Error can't find t_reordering in section dl_am"); return SRSRAN_ERROR; } field_asn1_enum_number t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit); - if (t_status_prohibit.parse(q["rlc_config"]["dl_am"])) { + if (t_status_prohibit.parse(root["dl_am"])) { ERROR("Error can't find t_status_prohibit in section dl_am"); return SRSRAN_ERROR; } @@ -1730,12 +1728,18 @@ int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) parser::section srb1("srb1_config"); bool srb1_present = false; srb1.set_optional(&srb1_present); - srb1.add_field(new field_srb(rrc_cfg_->srb1_cfg)); + + parser::section srb1_rlc_cfg("rlc_config"); + srb1.add_subsection(&srb1_rlc_cfg); + srb1_rlc_cfg.add_field(new field_srb(rrc_cfg_->srb1_cfg)); parser::section srb2("srb2_config"); bool srb2_present = false; srb2.set_optional(&srb2_present); - srb2.add_field(new field_srb(rrc_cfg_->srb2_cfg)); + + parser::section srb2_rlc_cfg("rlc_config"); + srb2.add_subsection(&srb2_rlc_cfg); + srb2_rlc_cfg.add_field(new field_srb(rrc_cfg_->srb2_cfg)); parser::section qci("qci_config"); qci.add_field(new field_qci(rrc_cfg_->qci_cfg)); From 132f2aa6057b3c3ee851ec9688c302bbaf7f4866 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 4 Jun 2021 16:19:09 +0100 Subject: [PATCH 37/59] Added assert to make sure SRB id makes sense in apply_rlc_rb_updates --- srsenb/src/stack/rrc/rrc_ue.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 77f2aa2aa..d343d0b7a 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -18,6 +18,7 @@ #include "srsenb/hdr/stack/rrc/ue_rr_cfg.h" #include "srsran/asn1/rrc_utils.h" #include "srsran/common/enb_events.h" +#include "srsran/common/srsran_assert.h" #include "srsran/common/standard_streams.h" #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" @@ -1411,6 +1412,7 @@ void rrc::ue::apply_pdcp_drb_updates(const rr_cfg_ded_s& pending_rr_cfg) void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) { for (const srb_to_add_mod_s& srb : pending_rr_cfg.srb_to_add_mod_list) { + srsran_assert(srb.srb_id == 1 || srb.srb_id == 2, "Trying to configure invalid SRB Id."); if (srb.srb_id == 1) { if (parent->cfg.srb1_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb1_cfg.explicit_value())); @@ -1423,10 +1425,9 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) } else { parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); } - } else { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); } } + if (pending_rr_cfg.drb_to_release_list.size() > 0) { for (uint8_t drb_id : pending_rr_cfg.drb_to_release_list) { parent->rlc->del_bearer(rnti, drb_to_lcid((lte_drb)drb_id)); From ff5fe5df14a818910ce4e4b4eebf58798b695723 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 2 Jul 2021 22:00:32 +0200 Subject: [PATCH 38/59] rf_uhd_imp: fix race in RF metrics --- lib/include/srsran/radio/radio.h | 1 + lib/src/phy/rf/rf_imp.c | 8 ++++---- lib/src/phy/rf/rf_uhd_imp.cc | 2 ++ lib/src/radio/radio.cc | 14 ++++++++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/include/srsran/radio/radio.h b/lib/include/srsran/radio/radio.h index 0b9f7e07c..0c206f1d6 100644 --- a/lib/include/srsran/radio/radio.h +++ b/lib/include/srsran/radio/radio.h @@ -90,6 +90,7 @@ private: std::vector rf_info = {}; std::vector rx_offset_n = {}; rf_metrics_t rf_metrics = {}; + std::mutex metrics_mutex; srslog::basic_logger& logger = srslog::fetch_basic_logger("RF", false); phy_interface_radio* phy = nullptr; cf_t* zeros = nullptr; diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index 6da4fa88d..9a6d25966 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -174,13 +174,13 @@ int srsran_rf_open_multi(srsran_rf_t* h, char* args, uint32_t nof_channels) int srsran_rf_close(srsran_rf_t* rf) { // Stop gain thread + pthread_mutex_lock(&rf->mutex); if (rf->thread_gain_run) { - pthread_mutex_lock(&rf->mutex); rf->thread_gain_run = false; - pthread_mutex_unlock(&rf->mutex); - pthread_cond_signal(&rf->cond); - pthread_join(rf->thread_gain, NULL); } + pthread_mutex_unlock(&rf->mutex); + pthread_cond_signal(&rf->cond); + pthread_join(rf->thread_gain, NULL); return ((rf_dev_t*)rf->dev)->srsran_rf_close(rf->handler); } diff --git a/lib/src/phy/rf/rf_uhd_imp.cc b/lib/src/phy/rf/rf_uhd_imp.cc index 4443f3603..be148f2f8 100644 --- a/lib/src/phy/rf/rf_uhd_imp.cc +++ b/lib/src/phy/rf/rf_uhd_imp.cc @@ -194,6 +194,7 @@ static std::array dummy_mem = {}; // For receiving static void log_overflow(rf_uhd_handler_t* h) { + std::unique_lock lock(h->tx_mutex); if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) { h->tx_state = RF_UHD_IMP_TX_STATE_END_OF_BURST; } @@ -208,6 +209,7 @@ static void log_overflow(rf_uhd_handler_t* h) static void log_late(rf_uhd_handler_t* h, bool is_rx) { + std::unique_lock lock(h->tx_mutex); if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) { h->tx_state = RF_UHD_IMP_TX_STATE_END_OF_BURST; } diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index fb0e46a98..74a75e7c4 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -979,6 +979,7 @@ srsran_rf_info_t* radio::get_info() bool radio::get_metrics(rf_metrics_t* metrics) { + std::lock_guard lock(metrics_mutex); *metrics = rf_metrics; rf_metrics = {}; return true; @@ -990,8 +991,11 @@ void radio::handle_rf_msg(srsran_rf_error_t error) return; } if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_OVERFLOW) { - rf_metrics.rf_o++; - rf_metrics.rf_error = true; + { + std::lock_guard lock(metrics_mutex); + rf_metrics.rf_o++; + rf_metrics.rf_error = true; + } logger.info("Overflow"); // inform PHY about overflow @@ -999,13 +1003,15 @@ void radio::handle_rf_msg(srsran_rf_error_t error) phy->radio_overflow(); } } else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_UNDERFLOW) { + logger.info("Underflow"); + std::lock_guard lock(metrics_mutex); rf_metrics.rf_u++; rf_metrics.rf_error = true; - logger.info("Underflow"); } else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_LATE) { + logger.info("Late (detected in %s)", error.opt ? "rx call" : "asynchronous thread"); + std::lock_guard lock(metrics_mutex); rf_metrics.rf_l++; rf_metrics.rf_error = true; - logger.info("Late (detected in %s)", error.opt ? "rx call" : "asynchronous thread"); } else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_RX) { logger.error("Fatal radio error occured."); phy->radio_failure(); From b5b2f8190ec1f4da1f6ca8e80bef3dedb3735511 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 2 Jul 2021 22:03:28 +0200 Subject: [PATCH 39/59] signal_handler: use std::atomic for running var --- lib/include/srsran/common/signal_handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srsran/common/signal_handler.h b/lib/include/srsran/common/signal_handler.h index ca700af74..41797d65d 100644 --- a/lib/include/srsran/common/signal_handler.h +++ b/lib/include/srsran/common/signal_handler.h @@ -31,7 +31,7 @@ extern "C" { // static vars required by signal handling static srslog::sink* log_sink = nullptr; -static bool running = true; +static std::atomic running = {true}; static void srsran_signal_handler(int signal) { From 2a31daca4ae6ef0e3a3f6f9778d115e29368601e Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 1 Jun 2021 12:35:01 +0100 Subject: [PATCH 40/59] enb,configuration: allow to specify enb specific max nof RLC retxs --- lib/include/srsran/srslog/shared_types.h | 4 +-- srsenb/hdr/stack/rrc/rrc_config.h | 12 ++++++-- srsenb/rb.conf.example | 12 ++++++++ srsenb/src/enb_cfg_parser.cc | 16 +++++++++-- srsenb/src/enb_cfg_parser.h | 4 +-- srsenb/src/stack/rrc/rrc.cc | 25 +++++----------- srsenb/src/stack/rrc/rrc_ue.cc | 36 ++++++++++++++++-------- srsenb/src/stack/rrc/ue_rr_cfg.cc | 6 ++-- 8 files changed, 73 insertions(+), 42 deletions(-) diff --git a/lib/include/srsran/srslog/shared_types.h b/lib/include/srsran/srslog/shared_types.h index 90aa8c6d0..d2cca6147 100644 --- a/lib/include/srsran/srslog/shared_types.h +++ b/lib/include/srsran/srslog/shared_types.h @@ -14,6 +14,7 @@ #define SRSLOG_SHARED_TYPES_H #include +#include namespace srslog { @@ -21,8 +22,7 @@ namespace srslog { using error_handler = std::function; /// Backend priority levels. -enum class backend_priority -{ +enum class backend_priority { /// Default priority of the operating system. normal, /// Thread will be given a high priority. diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index 55a5e83c0..676bf81be 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -31,12 +31,18 @@ struct rrc_cfg_sr_t { }; struct rrc_cfg_qci_t { - bool configured = false; + bool configured = false; + int enb_dl_max_retx_thres = -1; asn1::rrc::lc_ch_cfg_s::ul_specific_params_s_ lc_cfg; asn1::rrc::pdcp_cfg_s pdcp_cfg; asn1::rrc::rlc_cfg_c rlc_cfg; }; +struct srb_cfg_t { + int enb_dl_max_retx_thres = -1; + asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ rlc_cfg; +}; + struct rrc_cfg_t { uint32_t enb_id; ///< Required to pack SIB1 // Per eNB SIBs @@ -62,8 +68,8 @@ struct rrc_cfg_t { uint32_t max_mac_dl_kos; uint32_t max_mac_ul_kos; uint32_t rlf_release_timer_ms; - asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ srb1_cfg; - asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ srb2_cfg; + srb_cfg_t srb1_cfg; + srb_cfg_t srb2_cfg; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/rb.conf.example b/srsenb/rb.conf.example index c1d5b813a..27d997fc3 100644 --- a/srsenb/rb.conf.example +++ b/srsenb/rb.conf.example @@ -13,6 +13,9 @@ // t_status_prohibit = 0; // }; // }; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // } // srb2_config = { @@ -28,6 +31,9 @@ // t_status_prohibit = 0; // }; // }; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // } qci_config = ( @@ -53,6 +59,9 @@ qci_config = ( bucket_size_duration = 100; log_chan_group = 2; }; + enb_specific = { + dl_max_retx_thresh = 32; + }; }, { qci=9; @@ -78,6 +87,9 @@ qci_config = ( bucket_size_duration = 100; log_chan_group = 3; }; + enb_specific = { + dl_max_retx_thresh = 32; + }; } ); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index a0a0084fd..56605db4f 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -400,7 +400,7 @@ int phr_cnfg_parser::parse(libconfig::Setting& root) int field_srb::parse(libconfig::Setting& root) { // Parse RLC AM section - rlc_cfg_c* rlc_cfg = &cfg.set_explicit_value(); + rlc_cfg_c* rlc_cfg = &cfg.rlc_cfg.set_explicit_value(); if (root.exists("ul_am") && root.exists("dl_am")) { rlc_cfg->set_am(); } @@ -455,6 +455,11 @@ int field_srb::parse(libconfig::Setting& root) return SRSRAN_ERROR; } } + + if (root.exists("enb_specific")) { + cfg.enb_dl_max_retx_thres = (int)root["enb_specific"]["dl_max_retx_thresh"]; + } + return 0; } @@ -616,6 +621,11 @@ int field_qci::parse(libconfig::Setting& root) parser::field log_chan_group("log_chan_group", &lc_cfg->lc_ch_group); lc_cfg->lc_ch_group_present = not log_chan_group.parse(q["logical_channel_config"]); qcicfg.configured = true; + + if (q.exists("enb_specific")) { + qcicfg.enb_dl_max_retx_thres = (int)q["enb_specific"]["dl_max_retx_thresh"]; + } + cfg.insert(std::make_pair(qci, qcicfg)); } @@ -1752,10 +1762,10 @@ int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_) int ret = p.parse(); if (not srb1_present) { - rrc_cfg_->srb1_cfg.set_default_value(); + rrc_cfg_->srb1_cfg.rlc_cfg.set_default_value(); } if (not srb2_present) { - rrc_cfg_->srb2_cfg.set_default_value(); + rrc_cfg_->srb2_cfg.rlc_cfg.set_default_value(); } return ret; diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index 2e1b0301c..6ea75ffa2 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -149,13 +149,13 @@ private: class field_srb final : public parser::field_itf { public: - explicit field_srb(asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_& cfg_) : cfg(cfg_) {} + explicit field_srb(srb_cfg_t& cfg_) : cfg(cfg_) {} const char* get_name() override { return "field_srb"; } int parse(Setting& root) override; private: - asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_& cfg; + srb_cfg_t& cfg; }; class field_qci final : public parser::field_itf diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index b0d7a69b4..d80d3f81a 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -103,24 +103,13 @@ int32_t rrc::init(const rrc_cfg_t& cfg_, running = true; - if (cfg.srb1_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value) { - if (logger.debug.enabled()) { - asn1::json_writer js{}; - cfg.srb1_cfg.to_json(js); - logger.debug("SRB1 explicit configuration: %s", js.to_string().c_str()); - } - } else { - logger.debug("SRB1 default configuration"); - } - - if (cfg.srb2_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value) { - if (logger.debug.enabled()) { - asn1::json_writer js{}; - cfg.srb2_cfg.to_json(js); - logger.debug("SRB2 configuration: %s", js.to_string().c_str()); - } - } else { - logger.debug("SRB2 default configuration"); + if (logger.debug.enabled()) { + asn1::json_writer js{}; + cfg.srb1_cfg.rlc_cfg.to_json(js); + logger.debug("SRB1 configuration: %s", js.to_string().c_str()); + js = {}; + cfg.srb2_cfg.rlc_cfg.to_json(js); + logger.debug("SRB2 configuration: %s", js.to_string().c_str()); } return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index d343d0b7a..b0c60fce6 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1412,19 +1412,27 @@ void rrc::ue::apply_pdcp_drb_updates(const rr_cfg_ded_s& pending_rr_cfg) void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) { for (const srb_to_add_mod_s& srb : pending_rr_cfg.srb_to_add_mod_list) { - srsran_assert(srb.srb_id == 1 || srb.srb_id == 2, "Trying to configure invalid SRB Id."); + srb_cfg_t* srb_cfg; if (srb.srb_id == 1) { - if (parent->cfg.srb1_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb1_cfg.explicit_value())); - } else { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); - } + srb_cfg = &parent->cfg.srb1_cfg; } else if (srb.srb_id == 2) { - if (parent->cfg.srb2_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::make_rlc_config_t(parent->cfg.srb2_cfg.explicit_value())); - } else { - parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id)); + srb_cfg = &parent->cfg.srb2_cfg; + } else { + srsran_terminate("Invalid LTE SRB id=%d", srb.srb_id); + } + + if (srb_cfg->rlc_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) { + srsran::rlc_config_t rlc_cfg = srsran::make_rlc_config_t(srb_cfg->rlc_cfg.explicit_value()); + if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and srb_cfg->enb_dl_max_retx_thres > 0) { + rlc_cfg.am.max_retx_thresh = srb_cfg->enb_dl_max_retx_thres; } + parent->rlc->add_bearer(rnti, srb.srb_id, rlc_cfg); + } else { + srsran::rlc_config_t rlc_cfg = srsran::rlc_config_t::srb_config(srb.srb_id); + if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and srb_cfg->enb_dl_max_retx_thres > 0) { + rlc_cfg.am.max_retx_thresh = srb_cfg->enb_dl_max_retx_thres; + } + parent->rlc->add_bearer(rnti, srb.srb_id, rlc_cfg); } } @@ -1437,7 +1445,13 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg) if (not drb.rlc_cfg_present) { parent->logger.warning("Default RLC DRB config not supported"); } - parent->rlc->add_bearer(rnti, drb.lc_ch_id, srsran::make_rlc_config_t(drb.rlc_cfg)); + srsran::rlc_config_t rlc_cfg = srsran::make_rlc_config_t(drb.rlc_cfg); + const bearer_cfg_handler::erab_t& erab = bearer_list.get_erabs().at(drb.eps_bearer_id); + if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and + parent->cfg.qci_cfg.at(erab.qos_params.qci).enb_dl_max_retx_thres > 0) { + rlc_cfg.am.max_retx_thresh = parent->cfg.qci_cfg.at(erab.qos_params.qci).enb_dl_max_retx_thres; + } + parent->rlc->add_bearer(rnti, drb.lc_ch_id, rlc_cfg); } } diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index 7b7963a1c..1d56d339c 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -54,11 +54,11 @@ void fill_srbs_reconf(srb_to_add_mod_list_l& srbs, const srb_to_add_mod_list_l& { // NOTE: In case of Handover, the Reconf includes SRB1 if (srsran::find_rrc_obj_id(current_srbs, 1) == current_srbs.end()) { - add_srb(srbs, 1, enb_cfg.srb1_cfg); + add_srb(srbs, 1, enb_cfg.srb1_cfg.rlc_cfg); } if (srsran::find_rrc_obj_id(current_srbs, 2) == current_srbs.end()) { - add_srb(srbs, 2, enb_cfg.srb2_cfg); + add_srb(srbs, 2, enb_cfg.srb2_cfg.rlc_cfg); } } @@ -299,7 +299,7 @@ void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, // (Re)establish SRB1 rr_cfg.srb_to_add_mod_list_present = true; - add_srb(rr_cfg.srb_to_add_mod_list, 1, enb_cfg.srb1_cfg); + add_srb(rr_cfg.srb_to_add_mod_list, 1, enb_cfg.srb1_cfg.rlc_cfg); // Setup SR/CQI configs rr_cfg.phys_cfg_ded_present = true; From f42f8fcd7a80d041b41694839b3d5c228fb8ef31 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 15 Jul 2021 17:13:40 +0200 Subject: [PATCH 41/59] ctestconfig: update valgrind parameters to track origins --- CTestConfig.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CTestConfig.cmake b/CTestConfig.cmake index c83d049e0..10bc129d2 100644 --- a/CTestConfig.cmake +++ b/CTestConfig.cmake @@ -12,4 +12,4 @@ set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "my.cdash.org") set(CTEST_DROP_LOCATION "/submit.php?project=srsRAN") set(CTEST_DROP_SITE_CDASH TRUE) -set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=1 --trace-children=yes --leak-check=full --show-reachable=yes --vex-guest-max-insns=25") +set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=1 --trace-children=yes --leak-check=full --show-leak-kinds=all --track-origins=yes --show-reachable=yes --vex-guest-max-insns=25") From 67325ab5c19c26a2524b1330ab1221bc6b8cc11e Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 24 Jun 2021 11:23:36 +0100 Subject: [PATCH 42/59] add pdcch_cqi_offset parameter to enb.conf --- lib/include/srsran/interfaces/sched_interface.h | 1 + srsenb/enb.conf.example | 2 ++ srsenb/src/main.cc | 2 ++ srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc | 1 + 4 files changed, 6 insertions(+) diff --git a/lib/include/srsran/interfaces/sched_interface.h b/lib/include/srsran/interfaces/sched_interface.h index ec9d3a32d..d0e3eefe4 100644 --- a/lib/include/srsran/interfaces/sched_interface.h +++ b/lib/include/srsran/interfaces/sched_interface.h @@ -66,6 +66,7 @@ public: int init_ul_snr_value = 5; int init_dl_cqi = 5; float max_sib_coderate = 0.8; + int pdcch_cqi_offset = 0; }; struct cell_cfg_t { diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index f0f004b07..780ad967e 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -180,6 +180,7 @@ enable = false # init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant # init_dl_cqi: DL CQI value used before any CQI report is available to the eNB # max_sib_coderate: Upper bound on SIB and RAR grants coderate +# pdcch_cqi_offset: CQI offset in derivation of PDCCH aggregation level # ##################################################################### [scheduler] @@ -204,6 +205,7 @@ enable = false #init_ul_snr_value=5 #init_dl_cqi=5 #max_sib_coderate=0.3 +#pdcch_cqi_offset=0 ##################################################################### # eMBMS configuration options diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 6bb6aa002..028e25dc5 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -162,6 +162,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.init_ul_snr_value", bpo::value(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant") ("scheduler.init_dl_cqi", bpo::value(&args->stack.mac.sched.init_dl_cqi)->default_value(5), "DL CQI value used before any CQI report is available to the eNB") ("scheduler.max_sib_coderate", bpo::value(&args->stack.mac.sched.max_sib_coderate)->default_value(0.8), "Upper bound on SIB and RAR grants coderate") + ("scheduler.pdcch_cqi_offset", bpo::value(&args->stack.mac.sched.pdcch_cqi_offset)->default_value(0), "CQI offset in derivation of PDCCH aggregation level") + /* Downlink Channel emulator section */ diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index f3add09f4..c7ba14e42 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -279,6 +279,7 @@ uint32_t sched_ue_cell::get_aggr_level(uint32_t nof_bits) const } else { dl_cqi = dl_cqi_ctxt.get_avg_cqi(); } + dl_cqi = std::max(cell_cfg->sched_cfg->pdcch_cqi_offset + (int)dl_cqi, 0); return srsenb::get_aggr_level(nof_bits, dl_cqi, cell_cfg->sched_cfg->min_aggr_level, From 8708043a5f1f6aa70035ef6b9bd7b94e49f707c9 Mon Sep 17 00:00:00 2001 From: faluco Date: Mon, 21 Jun 2021 11:45:41 +0200 Subject: [PATCH 43/59] - Add date to log timestamps. - Print once per second the current timestamp into stdout, feature guarded by a config expert option. --- lib/src/srslog/formatters/text_formatter.cpp | 2 +- srsenb/enb.conf.example | 2 ++ srsenb/src/main.cc | 17 +++++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/src/srslog/formatters/text_formatter.cpp b/lib/src/srslog/formatters/text_formatter.cpp index d89ca50eb..ba6fb8185 100644 --- a/lib/src/srslog/formatters/text_formatter.cpp +++ b/lib/src/srslog/formatters/text_formatter.cpp @@ -43,7 +43,7 @@ static void format_metadata(const detail::log_entry_metadata& metadata, fmt::mem std::tm current_time = fmt::gmtime(std::chrono::high_resolution_clock::to_time_t(metadata.tp)); auto us_fraction = std::chrono::duration_cast(metadata.tp.time_since_epoch()).count() % 1000000u; - fmt::format_to(buffer, "{:%H:%M:%S}.{:06} ", current_time, us_fraction); + fmt::format_to(buffer, "{:%F}T{:%H:%M:%S}.{:06} ", current_time, current_time, us_fraction); // Format optional fields if present. if (!metadata.log_name.empty()) { diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 780ad967e..827184cf0 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -326,6 +326,7 @@ enable = false # tracing_enable: Write source code tracing information to a file. # tracing_filename: File path to use for tracing information. # tracing_buffcapacity: Maximum capacity in bytes the tracing framework can store. +# stdout_ts_enable: Prints once per second the timestamp into stdout. # pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance. # tx_amplitude: Transmit amplitude factor (set 0-1 to reduce PAPR) # rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds). @@ -353,6 +354,7 @@ enable = false #tracing_enable = true #tracing_filename = /tmp/enb_tracing.log #tracing_buffcapacity = 1000000 +#stdout_ts_enable = false #pregenerate_signals = false #tx_amplitude = 0.6 #rrc_inactivity_timer = 30000 diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 028e25dc5..da261acc2 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -45,7 +45,8 @@ namespace bpo = boost::program_options; /********************************************************************** * Program arguments processing ***********************************************************************/ -string config_file; +string config_file; +static bool stdout_ts_enable = false; void parse_args(all_args_t* args, int argc, char* argv[]) { @@ -226,6 +227,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.tracing_enable", bpo::value(&args->general.tracing_enable)->default_value(false), "Events tracing") ("expert.tracing_filename", bpo::value(&args->general.tracing_filename)->default_value("/tmp/enb_tracing.log"), "Tracing events filename") ("expert.tracing_buffcapacity", bpo::value(&args->general.tracing_buffcapacity)->default_value(1000000), "Tracing buffer capcity") + ("expert.stdout_ts_enable", bpo::value(&stdout_ts_enable)->default_value(false), "Prints once per second the timestamp into stdout") ("expert.rrc_inactivity_timer", bpo::value(&args->general.rrc_inactivity_timer)->default_value(30000), "Inactivity timer in ms.") ("expert.print_buffer_state", bpo::value(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds") ("expert.eea_pref_list", bpo::value(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).") @@ -622,7 +624,8 @@ int main(int argc, char* argv[]) enb->start_plot(); } } - int cnt = 0; + int cnt = 0; + int ts_cnt = 0; while (running) { if (args.general.print_buffer_state) { cnt++; @@ -631,6 +634,16 @@ int main(int argc, char* argv[]) enb->print_pool(); } } + if (stdout_ts_enable) { + if (++ts_cnt == 100) { + ts_cnt = 0; + char buff[64]; + std::time_t t = std::time(nullptr); + if (std::strftime(buff, sizeof(buff), "%FT%T", std::gmtime(&t))) { + std::cout << buff << '\n'; + } + } + } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } input.join(); From 357bc10a176f9c1d4474546593f547252e89aad5 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 May 2021 15:12:01 +0100 Subject: [PATCH 44/59] feature - make minimum SNR, under which the RRC is notified with UL KO, configurable --- lib/include/srsran/interfaces/enb_mac_interfaces.h | 1 + srsenb/enb.conf.example | 4 ++++ srsenb/src/main.cc | 1 + srsenb/src/stack/mac/mac.cc | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 5bd493f88..82fbf2371 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -25,6 +25,7 @@ struct mac_args_t { int nr_tb_size = -1; uint32_t nof_prealloc_ues; ///< Number of UE resources to pre-allocate at eNB startup uint32_t max_nof_kos; + int rlf_min_ul_snr_estim; }; /* Interface PHY -> MAC */ diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 827184cf0..d3c36dc18 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -338,6 +338,8 @@ enable = false # gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer). #ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds #ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds +# rlf_release_timer_ms: Time taken by eNB to release UE context after it detects an RLF +# rlf_min_ul_snr_estim: SNR threshold in dB below which the enb is notified with rlf ko # ##################################################################### [expert] @@ -369,3 +371,5 @@ enable = false #extended_cp = false #ts1_reloc_prep_timeout = 10000 #ts1_reloc_overall_timeout = 10000 +#rlf_release_timer_ms = 4000 +#rlf_min_ul_snr_estim = -2 diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index da261acc2..7f300756b 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -241,6 +241,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.extended_cp", bpo::value(&args->phy.extended_cp)->default_value(false), "Use extended cyclic prefix") ("expert.ts1_reloc_prep_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_prep_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds") ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds") + ("expert.rlf_min_ul_snr_estim", bpo::value(&args->stack.mac.rlf_min_ul_snr_estim)->default_value(-2), "SNR threshold in dB below which the eNB is notified with rlf ko.") // eMBMS section diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 21cfad988..ac06e20f4 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -401,7 +401,7 @@ int mac::snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr return SRSRAN_ERROR; } - rrc_h->set_radiolink_ul_state(rnti, snr > 0); + rrc_h->set_radiolink_ul_state(rnti, snr >= args.rlf_min_ul_snr_estim); return scheduler.ul_snr_info(tti_rx, rnti, enb_cc_idx, snr, (uint32_t)ch); } From b79481f74b270e9a0e5502b90cd4c5830059239a Mon Sep 17 00:00:00 2001 From: faluco Date: Thu, 15 Jul 2021 11:55:52 +0200 Subject: [PATCH 45/59] - Fix text formatter unit test for printing the date. --- lib/test/srslog/text_formatter_test.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/test/srslog/text_formatter_test.cpp b/lib/test/srslog/text_formatter_test.cpp index 15c9036c4..f6c79be59 100644 --- a/lib/test/srslog/text_formatter_test.cpp +++ b/lib/test/srslog/text_formatter_test.cpp @@ -37,7 +37,7 @@ static bool when_fully_filled_log_entry_then_everything_is_formatted() fmt::dynamic_format_arg_store store; text_formatter{}.format(build_log_entry_metadata(&store), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n"; + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n"; ASSERT_EQ(result, expected); @@ -53,7 +53,7 @@ static bool when_log_entry_without_name_is_passed_then_name_is_not_formatted() fmt::memory_buffer buffer; text_formatter{}.format(std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [Z] [ 10] Text 88\n"; + std::string expected = "1970-01-01T00:00:00.050000 [Z] [ 10] Text 88\n"; ASSERT_EQ(result, expected); @@ -69,7 +69,7 @@ static bool when_log_entry_without_tag_is_passed_then_tag_is_not_formatted() fmt::memory_buffer buffer; text_formatter{}.format(std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [ 10] Text 88\n"; + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [ 10] Text 88\n"; ASSERT_EQ(result, expected); @@ -85,7 +85,7 @@ static bool when_log_entry_without_context_is_passed_then_context_is_not_formatt fmt::memory_buffer buffer; text_formatter{}.format(std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [Z] Text 88\n"; + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] Text 88\n"; ASSERT_EQ(result, expected); @@ -102,7 +102,7 @@ static bool when_log_entry_with_hex_dump_is_passed_then_hex_dump_is_formatted() fmt::memory_buffer buffer; text_formatter{}.format(std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n" + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n" " 0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n" " 0010: 10 11 12 13\n"; @@ -176,7 +176,7 @@ static bool when_log_entry_with_only_context_is_passed_then_context_is_formatted fmt::memory_buffer buffer; text_formatter{}.format_ctx(ctx, std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Context dump for " + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Context dump for " "\"Complex Context\"\n" " > List: sector_list\n" " > Set: sector_metrics\n" @@ -218,7 +218,7 @@ static bool when_log_entry_with_context_and_message_is_passed_then_context_is_fo fmt::memory_buffer buffer; text_formatter{}.format_ctx(ctx, std::move(entry), buffer); std::string result = fmt::to_string(buffer); - std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] [[sector_metrics_type: event, " + std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] [[sector_metrics_type: event, " "sector_metrics_sector_id: 1, [ue_container_Throughput: 1.2 MB/s, " "ue_container_Address: 10.20.30.40, [RF_SNR: 5.1 dB, RF_PWR: -11 " "dBm][RF_SNR: 10.1 dB, RF_PWR: -20 dBm]][ue_container_Throughput: 10.2 " From 5d034b067ed2e0d76ea4b487890c353bc477a7ae Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 15 Jul 2021 21:23:35 +0200 Subject: [PATCH 46/59] Add option to rr.conf to select sub-band CQI K value (#3071) --- srsenb/hdr/stack/rrc/rrc_config_common.h | 2 ++ srsenb/rr.conf.example | 1 + srsenb/src/enb_cfg_parser.cc | 2 ++ srsenb/src/stack/rrc/ue_rr_cfg.cc | 10 ++++++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc_config_common.h b/srsenb/hdr/stack/rrc/rrc_config_common.h index 5c15df744..011102749 100644 --- a/srsenb/hdr/stack/rrc/rrc_config_common.h +++ b/srsenb/hdr/stack/rrc/rrc_config_common.h @@ -31,6 +31,8 @@ struct rrc_cfg_cqi_t { uint32_t nof_prb; uint32_t period; uint32_t m_ri; + bool is_subband_enabled; + uint32_t subband_k; bool simultaneousAckCQI; rrc_cfg_cqi_mode_t mode; }; diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index ee1b285a9..6c3bef5a9 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -47,6 +47,7 @@ phy_cnfg = //subframe = [0, 10, 20, 30]; // Optional vector of subframe indices every period where CQI resources will be allocated (default uses all) nof_prb = 1; m_ri = 8; // RI period in CQI period + //subband_k = 1; // If enabled and > 0, configures sub-band CQI reporting and defines K (see 36.213 7.2.2). If disabled, configures wideband CQI }; }; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 56605db4f..c97b3460d 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -736,6 +736,8 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) cqi_report_cnfg.add_field(new parser::field("period", &rrc_cfg_->cqi_cfg.period)); cqi_report_cnfg.add_field(new parser::field("m_ri", &rrc_cfg_->cqi_cfg.m_ri)); cqi_report_cnfg.add_field(new parser::field("nof_prb", &rrc_cfg_->cqi_cfg.nof_prb)); + cqi_report_cnfg.add_field( + new parser::field("subband_k", &rrc_cfg_->cqi_cfg.subband_k, &rrc_cfg_->cqi_cfg.is_subband_enabled)); cqi_report_cnfg.add_field(new parser::field("simultaneousAckCQI", &rrc_cfg_->cqi_cfg.simultaneousAckCQI)); cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg_->cqi_cfg.sf_mapping, &rrc_cfg_->cqi_cfg.nof_subframes, 1)); diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index 1d56d339c..acad59a39 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -120,8 +120,14 @@ void fill_cqi_report_enb_cfg(cqi_report_cfg_s& cqi_report_cfg, const rrc_cfg_t& } else { cqi_report_cfg.cqi_report_periodic_present = true; auto& cqi_setup = cqi_report_cfg.cqi_report_periodic.set_setup(); - cqi_setup.cqi_format_ind_periodic.set( - cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::wideband_cqi); + if (enb_cfg.cqi_cfg.subband_k == 0) { + cqi_setup.cqi_format_ind_periodic.set( + cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::wideband_cqi); + } else { + cqi_setup.cqi_format_ind_periodic.set( + cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi); + cqi_setup.cqi_format_ind_periodic.subband_cqi().k = enb_cfg.cqi_cfg.subband_k; + } cqi_setup.simul_ack_nack_and_cqi = enb_cfg.cqi_cfg.simultaneousAckCQI; } cqi_report_cfg.nom_pdsch_rs_epre_offset = 0; From f87f898641320344dcc60ca230e19e590d86fc4c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 30 Jun 2021 11:45:18 +0100 Subject: [PATCH 47/59] sched,nr: extend coreset pdcch allocation to UL --- srsenb/hdr/stack/mac/nr/sched_nr.h | 1 + srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 15 ++-- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 26 ++++--- .../hdr/stack/mac/nr/sched_nr_phy_helpers.h | 4 + srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 13 ++-- srsenb/src/stack/mac/nr/sched_nr.cc | 24 ++++-- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 63 ++++++++++------ .../src/stack/mac/nr/sched_nr_phy_helpers.cc | 43 +++++------ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 25 +++---- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 2 +- srsenb/test/mac/nr/sched_nr_test.cc | 75 ++++++++++++------- 11 files changed, 176 insertions(+), 115 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 5f04a6668..04f7039bc 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -50,6 +50,7 @@ private: // args sched_nr_impl::sched_params cfg; + srslog::basic_logger& logger; using sched_worker_manager = sched_nr_impl::sched_worker_manager; std::unique_ptr sched_workers; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index edbc47e95..a21345f5d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -15,6 +15,7 @@ #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" +#include "srsran/adt/optional.h" #include "srsran/adt/span.h" #include "srsran/common/phy_cfg_nr.h" #include "srsran/common/tti_point.h" @@ -51,8 +52,11 @@ public: using pusch_td_res_alloc_list = srsran::bounded_vector; struct bwp_cfg_t { + uint32_t bwp_id = 1; uint32_t start_rb = 0; uint32_t rb_width = 100; + + std::array, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets; }; struct cell_cfg_t { @@ -97,15 +101,14 @@ public: pdsch_list_t pdschs; }; - struct pusch_grant { - srsran_dci_ul_nr_t dci; - rbg_bitmap bitmap; + struct pusch_t { + srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration }; - using pusch_list = srsran::bounded_vector; + using pusch_list_t = srsran::bounded_vector; struct ul_tti_request_t { - tti_point pusch_tti; - srsran::bounded_vector pusch; + tti_point pusch_tti; + srsran::bounded_vector pusch; }; struct tti_request_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index c0f4c6882..97ab57f6a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -29,6 +29,7 @@ enum class pdcch_grant_type_t { sib, dl_data, ul_data }; class slot_ue; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; using pdcch_dl_t = sched_nr_interface::pdcch_dl_t; using pdcch_dl_list_t = sched_nr_interface::pdcch_dl_list_t; using pdcch_ul_t = sched_nr_interface::pdcch_ul_t; @@ -37,11 +38,11 @@ using pdcch_ul_list_t = sched_nr_interface::pdcch_ul_list_t; class coreset_region { public: - coreset_region(uint32_t bwp_id_, + coreset_region(const bwp_cfg_t& bwp_cfg_, + uint32_t coreset_id_, uint32_t slot_idx, - uint32_t nof_td_symbols, - uint32_t nof_freq_resources, - pdcch_dl_list_t& pdcch_list); + pdcch_dl_list_t& pdcch_dl_list, + pdcch_ul_list_t& pdcch_ul_list); void reset(); /** @@ -51,24 +52,24 @@ public: * @param user UE object or null in case of broadcast/RAR/paging allocation * @return if the allocation was successful */ - bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user = nullptr); + bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, slot_ue* user = nullptr); void rem_last_dci(); - uint32_t get_td_symbols() const { return nof_symbols; } + uint32_t get_td_symbols() const { return coreset_cfg->duration; } uint32_t get_freq_resources() const { return nof_freq_res; } - uint32_t nof_cces() const { return nof_freq_res * nof_symbols; } + uint32_t nof_cces() const { return nof_freq_res * get_td_symbols(); } size_t nof_allocs() const { return dfs_tree.size(); } private: - uint32_t bwp_id; - uint32_t slot_idx; - uint32_t nof_symbols; - uint32_t nof_freq_res; + const bwp_cfg_t* bwp_cfg; + const srsran_coreset_t* coreset_cfg; + uint32_t coreset_id; + uint32_t slot_idx; + uint32_t nof_freq_res = 0; // List of PDCCH grants struct alloc_record { - uint32_t coreset_id; uint32_t aggr_idx; uint32_t idx; pdcch_grant_type_t alloc_type; @@ -76,6 +77,7 @@ private: }; srsran::bounded_vector dci_list; pdcch_dl_list_t& pdcch_dl_list; + pdcch_ul_list_t& pdcch_ul_list; // DFS decision tree of PDCCH grants struct tree_node { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h index d72582209..f47893f41 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h @@ -26,6 +26,10 @@ void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_s class slot_ue; void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci); void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci); +void fill_sch_ue(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch); } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 23602693e..917d51845 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -28,7 +28,7 @@ using pusch_bitmap = srsran::bounded_bitset<25, true>; using pdsch_t = sched_nr_interface::pdsch_t; using pdsch_list_t = sched_nr_interface::pdsch_list_t; -using pusch_list = sched_nr_interface::pusch_list; +using pusch_list = sched_nr_interface::pusch_list_t; struct pucch_t {}; @@ -36,6 +36,7 @@ const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; struct bwp_slot_grid { + uint32_t bwp_id; pdcch_dl_list_t pdcch_dl_list; pdcch_ul_list_t pdcch_ul_list; slot_coreset_list coresets; @@ -53,10 +54,12 @@ struct bwp_slot_grid { struct bwp_res_grid { bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); - bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; }; - const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; }; - uint32_t id() const { return bwp_id; } - uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; } + bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; }; + const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; }; + uint32_t id() const { return bwp_id; } + uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; } + const sched_cell_params& cell_params() const { return *cell_cfg; } + const bwp_cfg_t& bwp_cfg() const { return cell_cfg->cell_cfg.bwps[id() - 1]; } private: uint32_t bwp_id; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 4ab1f74ee..4fd45b01f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -81,7 +81,9 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)) {} +sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : + cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)), logger(srslog::fetch_basic_logger("MAC")) +{} sched_nr::~sched_nr() {} @@ -156,15 +158,21 @@ void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti) }); } +#define VERIFY_INPUT(cond, msg, ...) \ + do { \ + if (not(cond)) { \ + srslog::fetch_basic_logger("MAC").warning(msg, ##__VA_ARGS__); \ + return SRSRAN_ERROR; \ + } \ + } while (0) + int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg) { - const srslog::basic_logger& logger = srslog::fetch_basic_logger("MAC"); - if (std::count(&uecfg.phy_cfg.pdcch.coreset_present[0], - &uecfg.phy_cfg.pdcch.coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET], - true) == 0) { - logger.warning("Provided rnti=0x%x configuration does not contain any coreset", rnti); - return SRSRAN_ERROR; - } + VERIFY_INPUT(std::count(&uecfg.phy_cfg.pdcch.coreset_present[0], + &uecfg.phy_cfg.pdcch.coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET], + true) > 0, + "Provided rnti=0x%x configuration does not contain any coreset", + rnti); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 49e7d7c90..e21b45f0a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -16,22 +16,22 @@ namespace srsenb { namespace sched_nr_impl { -coreset_region::coreset_region(uint32_t bwp_id_, +coreset_region::coreset_region(const bwp_cfg_t& bwp_cfg_, + uint32_t coreset_id_, uint32_t slot_idx_, - uint32_t nof_td_symbols, - uint32_t nof_freq_resources, - pdcch_dl_list_t& pdcch_list_) : - bwp_id(bwp_id_), + pdcch_dl_list_t& pdcch_dl_list_, + pdcch_ul_list_t& pdcch_ul_list_) : + bwp_cfg(&bwp_cfg_), + coreset_cfg(&bwp_cfg_.coresets[coreset_id_ - 1].value()), + coreset_id(coreset_id_), slot_idx(slot_idx_), - nof_symbols(nof_td_symbols), - nof_freq_res(nof_freq_resources), - pdcch_dl_list(pdcch_list_) + pdcch_dl_list(pdcch_dl_list_), + pdcch_ul_list(pdcch_ul_list_) { - srsran_assert(nof_td_symbols <= SRSRAN_CORESET_DURATION_MAX, + const bool* res_active = &coreset_cfg->freq_resources[0]; + nof_freq_res = std::count(res_active, res_active + SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, true); + srsran_assert(get_td_symbols() <= SRSRAN_CORESET_DURATION_MAX, "Possible number of time-domain OFDM symbols in CORESET must be within {1,2,3}"); - srsran_assert(nof_freq_resources <= SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, - "Provided number of CORESET freq domain resources=%d is too high", - nof_freq_resources); } void coreset_region::reset() @@ -40,9 +40,10 @@ void coreset_region::reset() saved_dfs_tree.clear(); dci_list.clear(); pdcch_dl_list.clear(); + pdcch_ul_list.clear(); } -bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user) +bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, slot_ue* user) { srsran_assert(aggr_idx <= 4, "Invalid DCI aggregation level=%d", 1U << aggr_idx); srsran_assert((user == nullptr) xor @@ -54,9 +55,13 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, record.ue = user; record.aggr_idx = aggr_idx; record.alloc_type = alloc_type; - record.idx = pdcch_dl_list.size(); - record.coreset_id = coreset_id; - pdcch_dl_list.emplace_back(); + if (record.alloc_type == pdcch_grant_type_t::ul_data) { + record.idx = pdcch_ul_list.size(); + pdcch_ul_list.emplace_back(); + } else { + record.idx = pdcch_dl_list.size(); + pdcch_dl_list.emplace_back(); + } // Try to allocate grant. If it fails, attempt the same grant, but using a different permutation of past grant DCI // positions @@ -74,7 +79,11 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, // Revert steps to initial state, before dci record allocation was attempted dfs_tree = saved_dfs_tree; - pdcch_dl_list.pop_back(); + if (record.alloc_type == pdcch_grant_type_t::ul_data) { + pdcch_ul_list.pop_back(); + } else { + pdcch_dl_list.pop_back(); + } return false; } @@ -84,8 +93,12 @@ void coreset_region::rem_last_dci() // Remove DCI record dfs_tree.pop_back(); + if (dci_list.back().alloc_type == pdcch_grant_type_t::ul_data) { + pdcch_ul_list.pop_back(); + } else { + pdcch_dl_list.pop_back(); + } dci_list.pop_back(); - pdcch_dl_list.pop_back(); } bool coreset_region::get_next_dfs() @@ -141,8 +154,14 @@ bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_d // Allocation successful node.total_mask |= node.current_mask; alloc_dfs.push_back(node); - pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx]; - pdcch_dl.dci.ctx.location = node.dci_pos; + // set new DCI position + if (record.alloc_type == pdcch_grant_type_t::ul_data) { + pdcch_ul_t& pdcch_ul = pdcch_ul_list[record.idx]; + pdcch_ul.dci.ctx.location = node.dci_pos; + } else { + pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx]; + pdcch_dl.dci.ctx.location = node.dci_pos; + } return true; } @@ -154,8 +173,8 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor switch (record.alloc_type) { case pdcch_grant_type_t::dl_data: return record.ue->cfg->cc_params[record.ue->cc] - .bwps[bwp_id] - .coresets[record.coreset_id] + .bwps[bwp_cfg->bwp_id - 1] + .coresets[coreset_id - 1] .cce_positions[slot_idx][record.aggr_idx]; default: break; diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc index c4f014ee6..56eb72752 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc @@ -66,36 +66,37 @@ void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_s } } -void fill_dci_harq(const harq_proc& h, srsran_dci_dl_nr_t& dci) +template +void fill_dci_common(const slot_ue& ue, DciDlOrUl& dci) { - dci.pid = h.pid; - dci.ndi = h.ndi(); - dci.mcs = h.mcs(); + dci.bwp_id = ue.bwp_id; + dci.cc_id = ue.cc; + dci.ctx.rnti = ue.rnti; + dci.ctx.rnti_type = srsran_rnti_type_c; + dci.tpc = 1; + // harq + harq_proc* h = std::is_same::value ? ue.h_dl : ue.h_ul; + dci.pid = h->pid; + dci.ndi = h->ndi(); + dci.mcs = h->mcs(); } void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci) { - dci.bwp_id = ue.bwp_id; - dci.cc_id = ue.cc; - dci.ctx.rnti = ue.rnti; - dci.tpc = 1; - fill_dci_harq(*ue.h_dl, dci); -} - -void fill_dci_harq(const harq_proc& h, srsran_dci_ul_nr_t& dci) -{ - dci.pid = h.pid; - dci.ndi = h.ndi(); - dci.mcs = h.mcs(); + fill_dci_common(ue, dci); } void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci) { - dci.bwp_id = ue.bwp_id; - dci.cc_id = ue.cc; - dci.ctx.rnti = ue.rnti; - dci.tpc = 1; - fill_dci_harq(*ue.h_ul, dci); + fill_dci_common(ue, dci); +} + +void fill_sch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const sched_cell_params& cc_cfg, srsran_sch_cfg_nr_t& sch) +{ + sch.grant.rnti_type = srsran_rnti_type_c; + sch.grant.rnti = ue.rnti; + sch.grant.nof_layers = 1; + bitmap_to_prb_array(rbgmask, cc_cfg.cell_cfg.nof_prb, sch.grant); } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 276998309..2c0314c75 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -16,12 +16,13 @@ namespace srsenb { namespace sched_nr_impl { -using pusch_grant = sched_nr_interface::pusch_grant; +using pusch_t = sched_nr_interface::pusch_t; bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : - dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg) + dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg), bwp_id(bwp_id_) { - coresets.emplace_back(bwp_id_, slot_idx_, 1, cell_params.cell_cfg.bwps[bwp_id_].rb_width / 6, pdcch_dl_list); + const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported + coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdcch_dl_list, pdcch_ul_list); } void bwp_slot_grid::reset() @@ -72,9 +73,8 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) if ((pdsch_mask & dl_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 3, coreset_id = 0; - if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci( - pdcch_grant_type_t::dl_data, aggr_idx, coreset_id, &ue)) { + const uint32_t aggr_idx = 2, coreset_id = 1; + if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id - 1].alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -94,9 +94,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back(); fill_dci_ue_cfg(ue, pdcch.dci); pdsch_grants.emplace_back(); - pdsch_t& grant = pdsch_grants.back(); - grant.sch.grant.rnti = ue.rnti; - bitmap_to_prb_array(dl_mask, bwp_grid.nof_prbs(), grant.sch.grant); + fill_sch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch); pdsch_mask |= dl_mask; return alloc_result::success; @@ -117,9 +115,8 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 3, coreset_id = 0; - if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci( - pdcch_grant_type_t::ul_data, aggr_idx, coreset_id, &ue)) { + const uint32_t aggr_idx = 2, coreset_id = 1; + if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id - 1].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -139,9 +136,7 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back(); fill_dci_ue_cfg(ue, pdcch.dci); pusch_grants.emplace_back(); - pusch_grant& grant = pusch_grants.back(); - grant.dci.ctx.rnti = ue.rnti; - grant.bitmap = ul_mask; + fill_sch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch); pusch_mask |= ul_mask; return alloc_result::success; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 9e7a38107..541af8f59 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -34,7 +34,7 @@ ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg auto& coreset = bwp.coresets.back(); coreset.cfg = &phy_cfg.pdcch.coreset[csid]; for (auto& ss : bwp.search_spaces) { - if (ss.cfg->coreset_id == csid) { + if (ss.cfg->coreset_id == csid + 1) { coreset.ss_list.push_back(&ss); get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions); } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 9b622f0b6..8969eee1e 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -17,6 +17,36 @@ namespace srsenb { +srsran_coreset_t get_default_coreset() +{ + srsran_coreset_t coreset{}; + coreset.id = 1; + coreset.duration = 1; + coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { + coreset.freq_resources[i] = i < 8; + } + return coreset; +} + +sched_nr_interface::cell_cfg_t get_default_cell_cfg() +{ + sched_nr_interface::cell_cfg_t cell_cfg{}; + + cell_cfg.bwps.resize(1); + cell_cfg.bwps[0].coresets[0].emplace(get_default_coreset()); + return cell_cfg; +} +std::vector get_default_cells_cfg(uint32_t nof_sectors) +{ + std::vector cells; + cells.reserve(nof_sectors); + for (uint32_t i = 0; i < nof_sectors; ++i) { + cells.push_back(get_default_cell_cfg()); + } + return cells; +} + sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) { sched_nr_interface::ue_cfg_t uecfg{}; @@ -25,22 +55,22 @@ sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) uecfg.carriers[cc].active = true; } uecfg.phy_cfg.pdcch.coreset_present[0] = true; - uecfg.phy_cfg.pdcch.coreset[0].id = 0; - for (uint32_t i = 0; i < 100 / 6; ++i) { - uecfg.phy_cfg.pdcch.coreset[0].freq_resources[i] = true; - } - uecfg.phy_cfg.pdcch.coreset[0].duration = 1; - uecfg.phy_cfg.pdcch.search_space_present[0] = true; - uecfg.phy_cfg.pdcch.search_space[0].id = 0; - uecfg.phy_cfg.pdcch.search_space[0].coreset_id = 0; - uecfg.phy_cfg.pdcch.search_space[0].duration = 1; - uecfg.phy_cfg.pdcch.search_space[0].type = srsran_search_space_type_common_0; - uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[0] = 1; - uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[1] = 1; - uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[2] = 1; - uecfg.phy_cfg.pdcch.search_space[0].nof_candidates[3] = 1; - uecfg.phy_cfg.pdcch.search_space[0].nof_formats = 1; - uecfg.phy_cfg.pdcch.search_space[0].formats[0] = srsran_dci_format_nr_0_0; + uecfg.phy_cfg.pdcch.coreset[0] = get_default_coreset(); + + uecfg.phy_cfg.pdcch.search_space_present[0] = true; + auto& ss = uecfg.phy_cfg.pdcch.search_space[0]; + ss.id = 1; + ss.coreset_id = 1; + ss.duration = 1; + ss.type = srsran_search_space_type_common_0; + ss.nof_candidates[0] = 1; + ss.nof_candidates[1] = 1; + ss.nof_candidates[2] = 1; + ss.nof_candidates[3] = 0; + ss.nof_candidates[4] = 0; + ss.nof_formats = 1; + ss.formats[0] = srsran_dci_format_nr_1_0; + return uecfg; } @@ -87,13 +117,11 @@ struct task_job_manager { void sched_nr_cfg_serialized_test() { - auto& mac_logger = srslog::fetch_basic_logger("MAC"); - uint32_t max_nof_ttis = 1000, nof_sectors = 2; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; - std::vector cells_cfg(nof_sectors); + std::vector cells_cfg = get_default_cells_cfg(nof_sectors); sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); @@ -121,13 +149,11 @@ void sched_nr_cfg_serialized_test() void sched_nr_cfg_parallel_cc_test() { - auto& mac_logger = srslog::fetch_basic_logger("MAC"); - uint32_t max_nof_ttis = 1000; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; - std::vector cells_cfg(4); + std::vector cells_cfg = get_default_cells_cfg(4); sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); @@ -161,9 +187,8 @@ void sched_nr_cfg_parallel_sf_test() task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; - cfg.nof_concurrent_subframes = 2; - std::vector cells_cfg; - cells_cfg.resize(nof_sectors); + cfg.nof_concurrent_subframes = 2; + std::vector cells_cfg = get_default_cells_cfg(nof_sectors); sched_nr sched(cfg); sched.cell_cfg(cells_cfg); From bcc374c2cd9df431b896289939af0a38dc2f2b85 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 1 Jul 2021 16:36:49 +0100 Subject: [PATCH 48/59] implement TDD DL vs UL slot activation --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 21 +++-- .../hdr/stack/mac/nr/sched_nr_phy_helpers.h | 24 ++++-- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 20 ++--- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 10 ++- srsenb/src/stack/mac/nr/sched_nr.cc | 2 +- .../src/stack/mac/nr/sched_nr_phy_helpers.cc | 81 +++++++++++++++---- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 35 +++++--- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 28 ++++--- srsenb/test/mac/nr/sched_nr_test.cc | 21 ++++- 9 files changed, 170 insertions(+), 72 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index a21345f5d..4f1d6ea18 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -26,12 +26,10 @@ namespace srsenb { const static size_t SCHED_NR_MAX_CARRIERS = 4; const static uint16_t SCHED_NR_INVALID_RNTI = 0; -const static size_t SCHED_NR_MAX_PDSCH_DATA = 16; const static size_t SCHED_NR_MAX_NOF_RBGS = 25; -const static size_t SCHED_NR_MAX_UL_ALLOCS = 16; const static size_t SCHED_NR_MAX_TB = 1; const static size_t SCHED_NR_MAX_HARQ = 16; -const static size_t SCHED_NR_MAX_BWP_PER_CELL = 1; +const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; class sched_nr_interface { @@ -39,17 +37,19 @@ public: using pdcch_bitmap = srsran::bounded_bitset; using rbg_bitmap = srsran::bounded_bitset; + static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS; + ///// Configuration ///// struct pdsch_td_res_alloc { uint8_t k0 = 0; // 0..32 uint8_t k1 = 4; // 0..32 }; - using pdsch_td_res_alloc_list = srsran::bounded_vector; + using pdsch_td_res_alloc_list = srsran::bounded_vector; struct pusch_td_res_alloc { uint8_t k2 = 4; // 0..32 }; - using pusch_td_res_alloc_list = srsran::bounded_vector; + using pusch_td_res_alloc_list = srsran::bounded_vector; struct bwp_cfg_t { uint32_t bwp_id = 1; @@ -62,6 +62,7 @@ public: struct cell_cfg_t { uint32_t nof_prb = 100; uint32_t nof_rbg = 25; + srsran_tdd_config_nr_t tdd = {}; srsran::bounded_vector bwps{1}; }; @@ -83,8 +84,6 @@ public: ///// Sched Result ///// - const static int MAX_GRANTS = 64; - using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; using pdcch_dl_list_t = srsran::bounded_vector; @@ -93,7 +92,7 @@ public: struct pdsch_t { srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration }; - using pdsch_list_t = srsran::bounded_vector; + using pdsch_list_t = srsran::bounded_vector; struct dl_tti_request_t { tti_point pdsch_tti; @@ -104,11 +103,11 @@ public: struct pusch_t { srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration }; - using pusch_list_t = srsran::bounded_vector; + using pusch_list_t = srsran::bounded_vector; struct ul_tti_request_t { - tti_point pusch_tti; - srsran::bounded_vector pusch; + tti_point pusch_tti; + srsran::bounded_vector pusch; }; struct tti_request_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h index f47893f41..c9e3c81b4 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h @@ -21,15 +21,23 @@ namespace sched_nr_impl { uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); -void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant); - class slot_ue; -void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci); -void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci); -void fill_sch_ue(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch); +void fill_dci_ue_cfg(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_dci_dl_nr_t& dci); +void fill_dci_ue_cfg(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_dci_ul_nr_t& dci); +void fill_pdsch_ue(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch); +void fill_pusch_ue(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch); } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 917d51845..5cda79af1 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -36,15 +36,17 @@ const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; struct bwp_slot_grid { - uint32_t bwp_id; - pdcch_dl_list_t pdcch_dl_list; - pdcch_ul_list_t pdcch_ul_list; - slot_coreset_list coresets; - pdsch_bitmap dl_rbgs; - pdsch_list_t pdsch_grants; - pusch_bitmap ul_rbgs; - pusch_list pusch_grants; - srsran::bounded_vector pucch_grants; + uint32_t bwp_id; + uint32_t slot_idx; + bool is_dl, is_ul; + pdcch_dl_list_t pdcch_dl_list; + pdcch_ul_list_t pdcch_ul_list; + slot_coreset_list coresets; + pdsch_bitmap dl_rbgs; + pdsch_list_t pdsch_grants; + pusch_bitmap ul_rbgs; + pusch_list pusch_grants; + srsran::bounded_vector pucch_grants; bwp_slot_grid() = default; explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index d1c2c5c66..255a25db2 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -92,7 +92,7 @@ private: class ue_carrier { public: - ue_carrier(uint16_t rnti, uint32_t cc, const ue_cfg_t& cfg); + ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_); slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_extended& cfg); void push_feedback(srsran::move_callback callback); @@ -106,7 +106,8 @@ public: harq_entity harq_ent; private: - const ue_cfg_t* cfg = nullptr; + const ue_cfg_t* cfg = nullptr; + const sched_cell_params& cell_params; resource_guard busy; tti_point last_tti_rx; @@ -117,7 +118,7 @@ private: class ue { public: - ue(uint16_t rnti, const ue_cfg_t& cfg); + ue(uint16_t rnti, const ue_cfg_t& cfg, const sched_params& sched_cfg_); slot_ue try_reserve(tti_point tti_rx, uint32_t cc); @@ -128,7 +129,8 @@ public: std::array, SCHED_NR_MAX_CARRIERS> carriers; private: - const uint16_t rnti; + const uint16_t rnti; + const sched_params& sched_cfg; bool pending_sr = false; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 4fd45b01f..ff386dd4b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -107,7 +107,7 @@ void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg) void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) { if (not ue_db.contains(rnti)) { - ue_db.insert(rnti, std::unique_ptr(new ue{rnti, uecfg})); + ue_db.insert(rnti, std::unique_ptr(new ue{rnti, uecfg, cfg})); } else { ue_db[rnti]->set_cfg(uecfg); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc index 56eb72752..d9171b6fd 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc @@ -53,27 +53,45 @@ uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_ return P; } -void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant) +void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran::span prbs) { uint32_t count = 0; - grant.nof_prb = bwp_nof_prb; for (uint32_t rbg = 0; rbg < bitmap.size(); ++rbg) { bool val = bitmap.test(rbg); uint32_t rbg_size = get_rbg_size(bwp_nof_prb, 0, true, rbg); - for (uint32_t prb = count; prb < count + rbg_size; ++prb) { - grant.prb_idx[prb] = val; + for (uint32_t prb_idx = count; prb_idx < count + rbg_size; ++prb_idx) { + prbs[prb_idx] = val; } } } -template -void fill_dci_common(const slot_ue& ue, DciDlOrUl& dci) +srsran::interval find_first_interval(const rbgmask_t& mask) { - dci.bwp_id = ue.bwp_id; - dci.cc_id = ue.cc; - dci.ctx.rnti = ue.rnti; - dci.ctx.rnti_type = srsran_rnti_type_c; - dci.tpc = 1; + int rb_start = mask.find_lowest(0, mask.size()); + if (rb_start != -1) { + int rb_end = mask.find_lowest(rb_start + 1, mask.size(), false); + return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)}; + } + return {}; +} + +int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb) +{ + srsran::interval interv = find_first_interval(bitmap); + srsran_assert(interv.length() == bitmap.count(), "Trying to acquire riv for non-contiguous bitmap"); + return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length()); +} + +template +void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci) +{ + // Note: PDCCH DCI position already filled at this point + dci.bwp_id = ue.bwp_id; + dci.cc_id = ue.cc; + dci.freq_domain_assigment = bitmap_to_riv(bitmap, cc_cfg.cell_cfg.nof_prb); + dci.ctx.rnti = ue.rnti; + dci.ctx.rnti_type = srsran_rnti_type_c; + dci.tpc = 1; // harq harq_proc* h = std::is_same::value ? ue.h_dl : ue.h_ul; dci.pid = h->pid; @@ -81,22 +99,51 @@ void fill_dci_common(const slot_ue& ue, DciDlOrUl& dci) dci.mcs = h->mcs(); } -void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci) +void fill_dci_ue_cfg(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_dci_dl_nr_t& dci) { - fill_dci_common(ue, dci); + fill_dci_common(ue, rbgmask, cc_cfg, dci); } -void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci) +void fill_dci_ue_cfg(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_dci_ul_nr_t& dci) { - fill_dci_common(ue, dci); + fill_dci_common(ue, rbgmask, cc_cfg, dci); } -void fill_sch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const sched_cell_params& cc_cfg, srsran_sch_cfg_nr_t& sch) +void fill_sch_ue_common(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch) { sch.grant.rnti_type = srsran_rnti_type_c; sch.grant.rnti = ue.rnti; sch.grant.nof_layers = 1; - bitmap_to_prb_array(rbgmask, cc_cfg.cell_cfg.nof_prb, sch.grant); + sch.grant.nof_prb = cc_cfg.cell_cfg.nof_prb; +} + +void fill_pdsch_ue(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch) +{ + fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); + sch.grant.k = ue.cc_cfg->pdsch_res_list[0].k0; + sch.grant.dci_format = srsran_dci_format_nr_1_0; +} + +void fill_pusch_ue(const slot_ue& ue, + const rbgmask_t& rbgmask, + const sched_cell_params& cc_cfg, + srsran_sch_cfg_nr_t& sch) +{ + fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); + sch.grant.k = ue.cc_cfg->pusch_res_list[0].k2; + sch.grant.dci_format = srsran_dci_format_nr_0_1; } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 2c0314c75..d3d5971d0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -18,8 +18,15 @@ namespace sched_nr_impl { using pusch_t = sched_nr_interface::pusch_t; +#define NUMEROLOGY_IDX 0 + bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : - dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg), bwp_id(bwp_id_) + dl_rbgs(cell_params.cell_cfg.nof_rbg), + ul_rbgs(cell_params.cell_cfg.nof_rbg), + bwp_id(bwp_id_), + slot_idx(slot_idx_), + is_dl(srsran_tdd_nr_is_dl(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)), + is_ul(srsran_tdd_nr_is_ul(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) { const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdcch_dl_list, pdcch_ul_list); @@ -64,12 +71,17 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - pdsch_list_t& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants; + bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_tti]; + if (not bwp_pdsch_slot.is_dl) { + logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx); + return alloc_result::no_sch_space; + } + pdsch_list_t& pdsch_grants = bwp_pdsch_slot.pdsch_grants; if (pdsch_grants.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pdsch_mask = bwp_grid[ue.pdsch_tti].dl_rbgs; + rbgmask_t& pdsch_mask = bwp_pdsch_slot.dl_rbgs; if ((pdsch_mask & dl_mask).any()) { return alloc_result::sch_collision; } @@ -92,9 +104,9 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) // Allocation Successful pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back(); - fill_dci_ue_cfg(ue, pdcch.dci); + fill_dci_ue_cfg(ue, dl_mask, bwp_grid.cell_params(), pdcch.dci); pdsch_grants.emplace_back(); - fill_sch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch); + fill_pdsch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch); pdsch_mask |= dl_mask; return alloc_result::success; @@ -106,12 +118,17 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } - pusch_list& pusch_grants = bwp_grid[ue.pusch_tti].pusch_grants; + auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti]; + if (not bwp_pusch_slot.is_ul) { + logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx); + return alloc_result::no_sch_space; + } + pusch_list& pusch_grants = bwp_pusch_slot.pusch_grants; if (pusch_grants.full()) { logger.warning("SCHED: Maximum number of UL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pusch_mask = bwp_grid[ue.pusch_tti].ul_rbgs; + rbgmask_t& pusch_mask = bwp_pusch_slot.ul_rbgs; if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } @@ -134,9 +151,9 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) // Allocation Successful pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back(); - fill_dci_ue_cfg(ue, pdcch.dci); + fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdcch.dci); pusch_grants.emplace_back(); - fill_sch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch); + fill_pusch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch); pusch_mask |= ul_mask; return alloc_result::success; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 541af8f59..2c313c1bf 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -52,7 +52,9 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const ue_cfg_t& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) {} +ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) : + rnti(rnti_), cc(cell_params_.cc), cfg(&uecfg_), cell_params(cell_params_) +{} void ue_carrier::push_feedback(srsran::move_callback callback) { @@ -91,13 +93,21 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1; sfu.dl_cqi = dl_cqi; sfu.ul_cqi = ul_cqi; - sfu.h_dl = harq_ent.find_pending_dl_retx(); - if (sfu.h_dl == nullptr) { - sfu.h_dl = harq_ent.find_empty_dl_harq(); + + const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; + if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_tti.sf_idx())) { + // If DL enabled + sfu.h_dl = harq_ent.find_pending_dl_retx(); + if (sfu.h_dl == nullptr) { + sfu.h_dl = harq_ent.find_empty_dl_harq(); + } } - sfu.h_ul = harq_ent.find_pending_ul_retx(); - if (sfu.h_ul == nullptr) { - sfu.h_ul = harq_ent.find_empty_ul_harq(); + if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_tti.sf_idx())) { + // If UL enabled + sfu.h_ul = harq_ent.find_pending_ul_retx(); + if (sfu.h_ul == nullptr) { + sfu.h_ul = harq_ent.find_empty_ul_harq(); + } } if (sfu.h_dl == nullptr and sfu.h_ul == nullptr) { @@ -110,12 +120,12 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ue::ue(uint16_t rnti_, const ue_cfg_t& cfg) : rnti(rnti_) +ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rnti(rnti_), sched_cfg(sched_cfg_) { ue_cfgs[0] = ue_cfg_extended(rnti, cfg); for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { - carriers[cc].reset(new ue_carrier(rnti, cc, cfg)); + carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc])); } } } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 8969eee1e..2130df547 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -20,7 +20,7 @@ namespace srsenb { srsran_coreset_t get_default_coreset() { srsran_coreset_t coreset{}; - coreset.id = 1; + coreset.id = 0; coreset.duration = 1; coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { @@ -33,8 +33,19 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() { sched_nr_interface::cell_cfg_t cell_cfg{}; - cell_cfg.bwps.resize(1); + cell_cfg.tdd.pattern1.period_ms = 10; + cell_cfg.tdd.pattern1.nof_dl_slots = 6; + cell_cfg.tdd.pattern1.nof_dl_symbols = 0; + cell_cfg.tdd.pattern1.nof_ul_slots = 4; + cell_cfg.tdd.pattern1.nof_ul_symbols = 0; + + // Disable pattern 2 + cell_cfg.tdd.pattern2.period_ms = 0; + + cell_cfg.bwps.resize(2); cell_cfg.bwps[0].coresets[0].emplace(get_default_coreset()); + cell_cfg.bwps[0].coresets[1].emplace(get_default_coreset()); + cell_cfg.bwps[0].coresets[1].value().id = 1; return cell_cfg; } std::vector get_default_cells_cfg(uint32_t nof_sectors) @@ -56,6 +67,7 @@ sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) } uecfg.phy_cfg.pdcch.coreset_present[0] = true; uecfg.phy_cfg.pdcch.coreset[0] = get_default_coreset(); + uecfg.phy_cfg.pdcch.coreset[0].id = 1; uecfg.phy_cfg.pdcch.search_space_present[0] = true; auto& ss = uecfg.phy_cfg.pdcch.search_space[0]; @@ -139,12 +151,13 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; sched_tester.update(out); tasks.finish_task(res); - TESTASSERT(res.dl_res.pdschs.size() == 1); + TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti + TX_ENB_DELAY).sf_idx()) or + res.dl_res.pdschs.size() == 1); } } tasks.print_results(); - TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors)); + TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); } void sched_nr_cfg_parallel_cc_test() From 23afc66a8662298d2eccb697cd50dfe2658920f3 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 2 Jul 2021 19:33:49 +0100 Subject: [PATCH 49/59] sched,nr: implementation of PUCCH HARQ allocation in NR --- srsenb/hdr/stack/mac/nr/sched_nr.h | 2 +- .../nr/{sched_nr_common.h => sched_nr_cfg.h} | 41 ++++++++++++++-- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 38 +++++++++------ srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 20 ++++---- .../hdr/stack/mac/nr/sched_nr_phy_helpers.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 24 ++++------ srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 31 +----------- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 2 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- .../{sched_nr_common.cc => sched_nr_cfg.cc} | 32 ++++++++++++- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 12 ++--- .../src/stack/mac/nr/sched_nr_phy_helpers.cc | 17 +++++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 47 +++++++++++-------- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 30 ------------ srsenb/src/stack/mac/nr/sched_nr_worker.cc | 6 +-- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 2 +- 17 files changed, 174 insertions(+), 138 deletions(-) rename srsenb/hdr/stack/mac/nr/{sched_nr_common.h => sched_nr_cfg.h} (70%) rename srsenb/src/stack/mac/nr/{sched_nr_common.cc => sched_nr_cfg.cc} (51%) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 04f7039bc..fd6a6ddad 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_H #define SRSRAN_SCHED_NR_H -#include "sched_nr_common.h" +#include "sched_nr_cfg.h" #include "sched_nr_interface.h" #include "sched_nr_ue.h" #include "srsran/adt/pool/cached_alloc.h" diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h similarity index 70% rename from srsenb/hdr/stack/mac/nr/sched_nr_common.h rename to srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 669d8f6b0..1bcf2d9ae 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_COMMON_H -#define SRSRAN_SCHED_NR_COMMON_H +#ifndef SRSRAN_SCHED_NR_CFG_H +#define SRSRAN_SCHED_NR_CFG_H #include "sched_nr_interface.h" #include "srsran/adt/bounded_bitset.h" @@ -27,6 +27,10 @@ namespace sched_nr_impl { const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS; +using pucch_resource_grant = sched_nr_interface::pucch_resource_grant; +using pucch_grant = sched_nr_interface::pucch_grant; +using pucch_list_t = sched_nr_interface::pucch_list_t; + using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; @@ -95,8 +99,39 @@ void get_dci_locs(const srsran_coreset_t& coreset, uint16_t rnti, bwp_cce_pos_list& cce_locs); +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using ue_cfg_t = sched_nr_interface::ue_cfg_t; +using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; + +class ue_cfg_extended : public ue_cfg_t +{ +public: + struct search_space_params { + srsran_search_space_t* cfg = nullptr; + }; + struct coreset_params { + srsran_coreset_t* cfg = nullptr; + std::vector ss_list; + bwp_cce_pos_list cce_positions; + }; + struct bwp_params { + std::vector search_spaces; + std::vector coresets; + }; + struct cc_params { + srsran::bounded_vector bwps; + }; + + uint16_t rnti; + std::vector cc_params; + + ue_cfg_extended() = default; + explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); +}; + } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_COMMON_H +#endif // SRSRAN_SCHED_NR_CFG_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 464c57814..1d5286a88 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_HARQ_H #define SRSRAN_SCHED_NR_HARQ_H -#include "sched_nr_common.h" +#include "sched_nr_cfg.h" #include "srsran/common/tti_point.h" #include diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 4f1d6ea18..d19855129 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -84,30 +84,38 @@ public: ///// Sched Result ///// - using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; - using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; - using pdcch_dl_list_t = srsran::bounded_vector; - using pdcch_ul_list_t = srsran::bounded_vector; + using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; + using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; - struct pdsch_t { - srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration + struct pdsch_grant { + srsran_dci_dl_nr_t dci = {}; }; - using pdsch_list_t = srsran::bounded_vector; + using pdsch_list_t = srsran::bounded_vector; struct dl_tti_request_t { - tti_point pdsch_tti; - pdcch_dl_list_t pdcchs; - pdsch_list_t pdschs; + tti_point pdsch_tti; + pdsch_list_t pdschs; }; - struct pusch_t { - srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration + struct pusch_grant { + srsran_dci_ul_nr_t dci = {}; }; - using pusch_list_t = srsran::bounded_vector; + using pusch_list_t = srsran::bounded_vector; + + struct pucch_resource_grant { + uint16_t rnti; + uint32_t resource_set_id; + uint32_t resource_id; + }; + struct pucch_grant { + pucch_resource_grant resource; + }; + using pucch_list_t = srsran::bounded_vector; struct ul_tti_request_t { - tti_point pusch_tti; - srsran::bounded_vector pusch; + tti_point pusch_tti; + pusch_list_t puschs; + pucch_list_t pucchs; }; struct tti_request_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index 97ab57f6a..261156990 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_PDCCH_H #define SRSRAN_SCHED_NR_PDCCH_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" #include "srsran/phy/common/phy_common_nr.h" @@ -29,11 +29,11 @@ enum class pdcch_grant_type_t { sib, dl_data, ul_data }; class slot_ue; -using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; -using pdcch_dl_t = sched_nr_interface::pdcch_dl_t; -using pdcch_dl_list_t = sched_nr_interface::pdcch_dl_list_t; -using pdcch_ul_t = sched_nr_interface::pdcch_ul_t; -using pdcch_ul_list_t = sched_nr_interface::pdcch_ul_list_t; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; +using pdsch_list_t = sched_nr_interface::pdsch_list_t; +using pdsch_grant = sched_nr_interface::pdsch_grant; +using pusch_list_t = sched_nr_interface::pusch_list_t; +using pusch_grant = sched_nr_interface::pusch_grant; class coreset_region { @@ -41,8 +41,8 @@ public: coreset_region(const bwp_cfg_t& bwp_cfg_, uint32_t coreset_id_, uint32_t slot_idx, - pdcch_dl_list_t& pdcch_dl_list, - pdcch_ul_list_t& pdcch_ul_list); + pdsch_list_t& pdcch_dl_list, + pusch_list_t& pdcch_ul_list); void reset(); /** @@ -76,8 +76,8 @@ private: slot_ue* ue; }; srsran::bounded_vector dci_list; - pdcch_dl_list_t& pdcch_dl_list; - pdcch_ul_list_t& pdcch_ul_list; + pdsch_list_t& pdcch_dl_list; + pusch_list_t& pdcch_ul_list; // DFS decision tree of PDCCH grants struct tree_node { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h index c9e3c81b4..071d779f3 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H #define SRSRAN_SCHED_NR_PHY_HELPERS_H -#include "sched_nr_common.h" +#include "sched_nr_cfg.h" namespace srsenb { namespace sched_nr_impl { @@ -39,6 +39,8 @@ void fill_pusch_ue(const slot_ue& ue, const sched_cell_params& cc_cfg, srsran_sch_cfg_nr_t& sch); +pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs); + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 5cda79af1..c73e78272 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -25,28 +25,24 @@ namespace sched_nr_impl { using pdsch_bitmap = srsran::bounded_bitset<25, true>; using pusch_bitmap = srsran::bounded_bitset<25, true>; -using pdsch_t = sched_nr_interface::pdsch_t; +using pdsch_t = sched_nr_interface::pdsch_grant; using pdsch_list_t = sched_nr_interface::pdsch_list_t; using pusch_list = sched_nr_interface::pusch_list_t; -struct pucch_t {}; - const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; struct bwp_slot_grid { - uint32_t bwp_id; - uint32_t slot_idx; - bool is_dl, is_ul; - pdcch_dl_list_t pdcch_dl_list; - pdcch_ul_list_t pdcch_ul_list; - slot_coreset_list coresets; - pdsch_bitmap dl_rbgs; - pdsch_list_t pdsch_grants; - pusch_bitmap ul_rbgs; - pusch_list pusch_grants; - srsran::bounded_vector pucch_grants; + uint32_t bwp_id; + uint32_t slot_idx; + bool is_dl, is_ul; + pdsch_bitmap dl_rbgs; + pusch_bitmap ul_rbgs; + pdsch_list_t pdschs; + pusch_list_t puschs; + slot_coreset_list coresets; + pucch_list_t pucchs; bwp_slot_grid() = default; explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 255a25db2..d56f11a43 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_UE_H #define SRSRAN_SCHED_NR_UE_H -#include "sched_nr_common.h" +#include "sched_nr_cfg.h" #include "sched_nr_harq.h" #include "sched_nr_interface.h" #include "srsran/adt/circular_map.h" @@ -24,35 +24,6 @@ namespace srsenb { namespace sched_nr_impl { -using ue_cfg_t = sched_nr_interface::ue_cfg_t; -using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; - -class ue_cfg_extended : public ue_cfg_t -{ -public: - struct search_space_params { - srsran_search_space_t* cfg = nullptr; - }; - struct coreset_params { - srsran_coreset_t* cfg = nullptr; - std::vector ss_list; - bwp_cce_pos_list cce_positions; - }; - struct bwp_params { - std::vector search_spaces; - std::vector coresets; - }; - struct cc_params { - srsran::bounded_vector bwps; - }; - - uint16_t rnti; - std::vector cc_params; - - ue_cfg_extended() = default; - explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); -}; - class ue_carrier; class slot_ue diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 23632a9d5..b7331a24b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_WORKER_H #define SRSRAN_SCHED_NR_WORKER_H -#include "sched_nr_common.h" +#include "sched_nr_cfg.h" #include "sched_nr_rb_grid.h" #include "sched_nr_ue.h" #include "srsran/adt/circular_array.h" diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index dee5663ec..2f18bc2c3 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,6 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_common.cc sched_nr_phy_helpers.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy_helpers.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr_common.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc similarity index 51% rename from srsenb/src/stack/mac/nr/sched_nr_common.cc rename to srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 3a239475a..ce61367c5 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_common.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" namespace srsenb { namespace sched_nr_impl { @@ -39,5 +39,35 @@ void get_dci_locs(const srsran_coreset_t& coreset, } } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_) +{ + cc_params.resize(carriers.size()); + for (uint32_t cc = 0; cc < cc_params.size(); ++cc) { + cc_params[cc].bwps.resize(1); + auto& bwp = cc_params[cc].bwps[0]; + for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) { + if (phy_cfg.pdcch.search_space_present[ssid]) { + bwp.search_spaces.emplace_back(); + bwp.search_spaces.back().cfg = &phy_cfg.pdcch.search_space[ssid]; + } + } + for (uint32_t csid = 0; csid < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++csid) { + if (phy_cfg.pdcch.coreset_present[csid]) { + bwp.coresets.emplace_back(); + auto& coreset = bwp.coresets.back(); + coreset.cfg = &phy_cfg.pdcch.coreset[csid]; + for (auto& ss : bwp.search_spaces) { + if (ss.cfg->coreset_id == csid + 1) { + coreset.ss_list.push_back(&ss); + get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions); + } + } + } + } + } +} + } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index e21b45f0a..298fcbfcd 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -19,14 +19,14 @@ namespace sched_nr_impl { coreset_region::coreset_region(const bwp_cfg_t& bwp_cfg_, uint32_t coreset_id_, uint32_t slot_idx_, - pdcch_dl_list_t& pdcch_dl_list_, - pdcch_ul_list_t& pdcch_ul_list_) : + pdsch_list_t& dl_list_, + pusch_list_t& ul_list_) : bwp_cfg(&bwp_cfg_), coreset_cfg(&bwp_cfg_.coresets[coreset_id_ - 1].value()), coreset_id(coreset_id_), slot_idx(slot_idx_), - pdcch_dl_list(pdcch_dl_list_), - pdcch_ul_list(pdcch_ul_list_) + pdcch_dl_list(dl_list_), + pdcch_ul_list(ul_list_) { const bool* res_active = &coreset_cfg->freq_resources[0]; nof_freq_res = std::count(res_active, res_active + SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, true); @@ -156,10 +156,10 @@ bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_d alloc_dfs.push_back(node); // set new DCI position if (record.alloc_type == pdcch_grant_type_t::ul_data) { - pdcch_ul_t& pdcch_ul = pdcch_ul_list[record.idx]; + pusch_grant& pdcch_ul = pdcch_ul_list[record.idx]; pdcch_ul.dci.ctx.location = node.dci_pos; } else { - pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx]; + pdsch_grant& pdcch_dl = pdcch_dl_list[record.idx]; pdcch_dl.dci.ctx.location = node.dci_pos; } return true; diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc index d9171b6fd..779f7c041 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc @@ -85,6 +85,7 @@ int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb) template void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci) { + const static uint32_t rv_idx[4] = {0, 2, 3, 1}; // Note: PDCCH DCI position already filled at this point dci.bwp_id = ue.bwp_id; dci.cc_id = ue.cc; @@ -97,6 +98,7 @@ void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cel dci.pid = h->pid; dci.ndi = h->ndi(); dci.mcs = h->mcs(); + dci.rv = rv_idx[h->nof_retx() % 4]; } void fill_dci_ue_cfg(const slot_ue& ue, @@ -146,5 +148,20 @@ void fill_pusch_ue(const slot_ue& ue, sch.grant.dci_format = srsran_dci_format_nr_0_1; } +pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs) +{ + if (ue.cfg->phy_cfg.pucch.enabled) { + for (uint32_t i = 0; i < SRSRAN_PUCCH_NR_MAX_NOF_SETS; ++i) { + const auto& rset = ue.cfg->phy_cfg.pucch.sets[i]; + if (rset.max_payload_size >= tbs) { + for (uint32_t sid = 0; sid < rset.nof_resources; ++sid) { + return pucch_resource_grant{ue.rnti, i, sid}; + } + } + } + } + return pucch_resource_grant{SRSRAN_INVALID_RNTI, 0, 0}; +} + } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index d3d5971d0..f0a433c26 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -16,8 +16,6 @@ namespace srsenb { namespace sched_nr_impl { -using pusch_t = sched_nr_interface::pusch_t; - #define NUMEROLOGY_IDX 0 bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : @@ -29,7 +27,7 @@ bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_ is_ul(srsran_tdd_nr_is_ul(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) { const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported - coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdcch_dl_list, pdcch_ul_list); + coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdschs, puschs); } void bwp_slot_grid::reset() @@ -39,10 +37,9 @@ void bwp_slot_grid::reset() } dl_rbgs.reset(); ul_rbgs.reset(); - pdsch_grants.clear(); - pdcch_dl_list.clear(); - pusch_grants.clear(); - pucch_grants.clear(); + pdschs.clear(); + puschs.clear(); + pucchs.clear(); } bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_), cell_cfg(&cell_cfg_) @@ -71,12 +68,14 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } + bwp_slot_grid& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti]; bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_tti]; + bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_tti]; if (not bwp_pdsch_slot.is_dl) { logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx); return alloc_result::no_sch_space; } - pdsch_list_t& pdsch_grants = bwp_pdsch_slot.pdsch_grants; + pdsch_list_t& pdsch_grants = bwp_pdsch_slot.pdschs; if (pdsch_grants.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; @@ -85,8 +84,8 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) if ((pdsch_mask & dl_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, coreset_id = 1; - if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id - 1].alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, &ue)) { + const uint32_t aggr_idx = 2, coreset_id = 0; + if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -102,12 +101,22 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) srsran_assert(ret, "Failed to allocate DL HARQ retx"); } + pucch_resource_grant pucch_res = find_pucch_resource(ue, bwp_uci_slot.ul_rbgs, tbs); + if (pucch_res.rnti != SRSRAN_INVALID_RNTI) { + // Could not find space in PUCCH for HARQ-ACK + bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); + return alloc_result::no_cch_space; + } + // Allocation Successful - pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back(); + pdsch_grant& pdcch = bwp_pdcch_slot.pdschs.back(); fill_dci_ue_cfg(ue, dl_mask, bwp_grid.cell_params(), pdcch.dci); - pdsch_grants.emplace_back(); - fill_pdsch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch); pdsch_mask |= dl_mask; + bwp_uci_slot.pucchs.emplace_back(); + pucch_grant& pucch = bwp_uci_slot.pucchs.back(); + pucch.resource = pucch_res; + bwp_uci_slot.ul_rbgs.set( + ue.cfg->phy_cfg.pucch.sets[pucch_res.resource_set_id].resources[pucch_res.resource_id].starting_prb); return alloc_result::success; } @@ -123,7 +132,7 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx); return alloc_result::no_sch_space; } - pusch_list& pusch_grants = bwp_pusch_slot.pusch_grants; + pusch_list& pusch_grants = bwp_pusch_slot.puschs; if (pusch_grants.full()) { logger.warning("SCHED: Maximum number of UL allocations reached"); return alloc_result::no_grant_space; @@ -132,8 +141,8 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, coreset_id = 1; - if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id - 1].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { + const uint32_t aggr_idx = 2, coreset_id = 0; + if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -150,10 +159,8 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) } // Allocation Successful - pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back(); - fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdcch.dci); - pusch_grants.emplace_back(); - fill_pusch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch); + pdsch_grant& pdsch = bwp_grid[ue.pdcch_tti].pdschs.back(); + fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdsch.dci); pusch_mask |= ul_mask; return alloc_result::success; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 2c313c1bf..1d22f5389 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -16,36 +16,6 @@ namespace srsenb { namespace sched_nr_impl { -ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_) -{ - cc_params.resize(carriers.size()); - for (uint32_t cc = 0; cc < cc_params.size(); ++cc) { - cc_params[cc].bwps.resize(1); - auto& bwp = cc_params[cc].bwps[0]; - for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) { - if (phy_cfg.pdcch.search_space_present[ssid]) { - bwp.search_spaces.emplace_back(); - bwp.search_spaces.back().cfg = &phy_cfg.pdcch.search_space[ssid]; - } - } - for (uint32_t csid = 0; csid < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++csid) { - if (phy_cfg.pdcch.coreset_present[csid]) { - bwp.coresets.emplace_back(); - auto& coreset = bwp.coresets.back(); - coreset.cfg = &phy_cfg.pdcch.coreset[csid]; - for (auto& ss : bwp.search_spaces) { - if (ss.cfg->coreset_id == csid + 1) { - coreset.ss_list.push_back(&ss); - get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions); - } - } - } - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) : ue_token(std::move(ue_token_)), rnti(rnti_), tti_rx(tti_rx_), cc(cc_) {} diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index d6a4dc8d9..ab3b63d5c 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -158,11 +158,11 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t // Copy requested TTI DL and UL sched result tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.dl_res.pdcchs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdcch_dl_list; - tti_req.dl_res.pdschs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdsch_grants; + tti_req.dl_res.pdschs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdschs; cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].reset(); tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.ul_res.pusch = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pusch_grants; + tti_req.ul_res.puschs = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].puschs; + tti_req.ul_res.pucchs = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pucchs; cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].reset(); // decrement the number of active workers diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index e6d9bffd7..fa28063dd 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -45,7 +45,7 @@ void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) { uint32_t cc = cc_out.cc; for (uint32_t i = 0; i < cc_out.dl_cc_result->pdschs.size(); ++i) { - const auto& data = cc_out.dl_cc_result->pdcchs[i]; + const auto& data = cc_out.dl_cc_result->pdschs[i]; if (data.dci.ctx.rnti != ctxt.rnti) { continue; } From 4f0b954cde18fb6f16ae1bb3c440c70e6eefa439 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 5 Jul 2021 18:13:41 +0100 Subject: [PATCH 50/59] sched,nr: changed scheduler nr api to not require slot_indication function --- srsenb/hdr/stack/mac/nr/sched_nr.h | 13 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 40 ++---- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 18 +-- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 13 +- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 28 +++-- srsenb/src/stack/mac/nr/sched_nr.cc | 125 +++++++++++++++---- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 8 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 25 ++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 102 +++++++++------ srsenb/test/mac/nr/sched_nr_sim_ue.cc | 7 +- srsenb/test/mac/nr/sched_nr_sim_ue.h | 10 +- srsenb/test/mac/nr/sched_nr_test.cc | 101 +++++++++------ 12 files changed, 292 insertions(+), 198 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index fd6a6ddad..4a0cbf4ea 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -30,6 +30,7 @@ class sched_worker_manager; } class ue_event_manager; +class sched_result_manager; class sched_nr final : public sched_nr_interface { @@ -39,13 +40,14 @@ public: int cell_cfg(srsran::const_span cell_list) override; void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override; - void slot_indication(tti_point tti_rx) override; - int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req) override; - void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_sr_info(tti_point tti_rx, uint16_t rnti) override; + int get_dl_sched(tti_point pdsch_tti, uint32_t cc, dl_sched_t& result) override; + int get_ul_sched(tti_point pdcch_tti, uint32_t cc, ul_sched_t& result) override; + private: + int generate_slot_result(tti_point pdcch_tti, uint32_t cc); void ue_cfg_impl(uint16_t rnti, const ue_cfg_t& cfg); // args @@ -59,8 +61,11 @@ private: std::mutex ue_db_mutex; ue_map_t ue_db; - // management of PHY UE feedback + // management of UE feedback std::unique_ptr pending_events; + + // management of Sched Result buffering + std::unique_ptr pending_results; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index d19855129..2b82bf83e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -84,23 +84,8 @@ public: ///// Sched Result ///// - using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; - using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; - - struct pdsch_grant { - srsran_dci_dl_nr_t dci = {}; - }; - using pdsch_list_t = srsran::bounded_vector; - - struct dl_tti_request_t { - tti_point pdsch_tti; - pdsch_list_t pdschs; - }; - - struct pusch_grant { - srsran_dci_ul_nr_t dci = {}; - }; - using pusch_list_t = srsran::bounded_vector; + using dl_sched_t = mac_interface_phy_nr::dl_sched_t; + using ul_sched_t = mac_interface_phy_nr::ul_sched_t; struct pucch_resource_grant { uint16_t rnti; @@ -112,22 +97,11 @@ public: }; using pucch_list_t = srsran::bounded_vector; - struct ul_tti_request_t { - tti_point pusch_tti; - pusch_list_t puschs; - pucch_list_t pucchs; - }; - - struct tti_request_t { - dl_tti_request_t dl_res; - ul_tti_request_t ul_res; - }; - - virtual ~sched_nr_interface() = default; - virtual int cell_cfg(srsran::const_span ue_cfg) = 0; - virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; - virtual void slot_indication(tti_point tti_rx) = 0; - virtual int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& result) = 0; + virtual ~sched_nr_interface() = default; + virtual int cell_cfg(srsran::const_span ue_cfg) = 0; + virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; + virtual int get_dl_sched(tti_point tti_rx, uint32_t cc, dl_sched_t& result) = 0; + virtual int get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; virtual void ul_sr_info(tti_point, uint16_t rnti) = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index 261156990..f7fe40bda 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -29,11 +29,11 @@ enum class pdcch_grant_type_t { sib, dl_data, ul_data }; class slot_ue; -using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; -using pdsch_list_t = sched_nr_interface::pdsch_list_t; -using pdsch_grant = sched_nr_interface::pdsch_grant; -using pusch_list_t = sched_nr_interface::pusch_list_t; -using pusch_grant = sched_nr_interface::pusch_grant; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; +using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; +using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; +using pdcch_dl_list_t = srsran::bounded_vector; +using pdcch_ul_list_t = srsran::bounded_vector; class coreset_region { @@ -41,8 +41,8 @@ public: coreset_region(const bwp_cfg_t& bwp_cfg_, uint32_t coreset_id_, uint32_t slot_idx, - pdsch_list_t& pdcch_dl_list, - pusch_list_t& pdcch_ul_list); + pdcch_dl_list_t& pdcch_dl_list, + pdcch_ul_list_t& pdcch_ul_list); void reset(); /** @@ -76,8 +76,8 @@ private: slot_ue* ue; }; srsran::bounded_vector dci_list; - pdsch_list_t& pdcch_dl_list; - pusch_list_t& pdcch_ul_list; + pdcch_dl_list_t& pdcch_dl_list; + pdcch_ul_list_t& pdcch_ul_list; // DFS decision tree of PDCCH grants struct tree_node { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index c73e78272..92a15f54c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -25,11 +25,6 @@ namespace sched_nr_impl { using pdsch_bitmap = srsran::bounded_bitset<25, true>; using pusch_bitmap = srsran::bounded_bitset<25, true>; -using pdsch_t = sched_nr_interface::pdsch_grant; -using pdsch_list_t = sched_nr_interface::pdsch_list_t; - -using pusch_list = sched_nr_interface::pusch_list_t; - const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; @@ -39,8 +34,8 @@ struct bwp_slot_grid { bool is_dl, is_ul; pdsch_bitmap dl_rbgs; pusch_bitmap ul_rbgs; - pdsch_list_t pdschs; - pusch_list_t puschs; + pdcch_dl_list_t dl_pdcchs; + pdcch_ul_list_t ul_pdcchs; slot_coreset_list coresets; pucch_list_t pucchs; @@ -52,8 +47,8 @@ struct bwp_slot_grid { struct bwp_res_grid { bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); - bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; }; - const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; }; + bwp_slot_grid& operator[](tti_point tti) { return slots[tti.to_uint() % slots.capacity()]; }; + const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.to_uint() % slots.capacity()]; }; uint32_t id() const { return bwp_id; } uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; } const sched_cell_params& cell_params() const { return *cell_cfg; } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index b7331a24b..0b4d4c45f 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -22,12 +22,12 @@ #include "srsran/adt/span.h" #include #include -#include namespace srsenb { namespace sched_nr_impl { -using slot_res_t = sched_nr_interface::tti_request_t; +using dl_sched_t = sched_nr_interface::dl_sched_t; +using ul_sched_t = sched_nr_interface::ul_sched_t; class slot_cc_worker { @@ -55,27 +55,31 @@ private: class sched_worker_manager { + struct slot_worker_ctxt { + std::mutex slot_mutex; // lock of all workers of the same slot. + std::condition_variable cvar; + tti_point tti_rx; + int nof_workers_waiting = 0; + std::atomic worker_count{0}; // variable shared across slot_cc_workers + std::vector workers; + }; + public: explicit sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_); sched_worker_manager(const sched_worker_manager&) = delete; sched_worker_manager(sched_worker_manager&&) = delete; ~sched_worker_manager(); - void reserve_workers(tti_point tti_rx); - void start_tti(tti_point tti_rx); - bool run_tti(tti_point tti_rx, uint32_t cc, sched_nr_interface::tti_request_t& req); - void end_tti(tti_point tti_rx); + void start_slot(tti_point tti_rx, srsran::move_callback process_feedback); + bool run_slot(tti_point tti_rx, uint32_t cc); + void release_slot(tti_point tti_rx); + bool get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); private: const sched_params& cfg; ue_map_t& ue_db; + std::mutex ue_db_mutex; - struct slot_worker_ctxt { - sem_t sf_sem; // lock of all workers of the same slot. unlocked by last slot_cc_worker - tti_point tti_rx; - std::atomic worker_count{0}; // variable shared across slot_cc_workers - std::vector workers; - }; std::vector > slot_ctxts; srsran::bounded_vector cell_grid_list; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index ff386dd4b..bd9022ff2 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -16,10 +16,7 @@ namespace srsenb { -using sched_nr_impl::sched_worker_manager; -using sched_nr_impl::ue; -using sched_nr_impl::ue_carrier; -using sched_nr_impl::ue_map_t; +using namespace sched_nr_impl; static int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg); @@ -44,7 +41,7 @@ public: feedback_list.back().cc = cc; feedback_list.back().callback = std::move(event); } - void new_tti() + void new_slot() { { std::lock_guard lock(common_mutex); @@ -81,6 +78,68 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class sched_result_manager +{ +public: + explicit sched_result_manager(uint32_t nof_cc_) + { + for (auto& v : results) { + v.resize(nof_cc_); + } + } + + dl_sched_t& add_dl_result(tti_point tti, uint32_t cc) + { + if (not has_dl_result(tti, cc)) { + results[tti.to_uint()][cc].tti_dl = tti; + results[tti.to_uint()][cc].dl_res = {}; + } + return results[tti.to_uint()][cc].dl_res; + } + ul_sched_t& add_ul_result(tti_point tti, uint32_t cc) + { + if (not has_ul_result(tti, cc)) { + results[tti.to_uint()][cc].tti_ul = tti; + results[tti.to_uint()][cc].ul_res = {}; + } + return results[tti.to_uint()][cc].ul_res; + } + + bool has_dl_result(tti_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].tti_dl == tti; } + + bool has_ul_result(tti_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].tti_ul == tti; } + + dl_sched_t pop_dl_result(tti_point tti, uint32_t cc) + { + if (has_dl_result(tti, cc)) { + results[tti.to_uint()][cc].tti_dl.reset(); + return results[tti.to_uint()][cc].dl_res; + } + return {}; + } + + ul_sched_t pop_ul_result(tti_point tti, uint32_t cc) + { + if (has_ul_result(tti, cc)) { + results[tti.to_uint()][cc].tti_ul.reset(); + return results[tti.to_uint()][cc].ul_res; + } + return {}; + } + +private: + struct slot_result_t { + tti_point tti_dl; + tti_point tti_ul; + dl_sched_t dl_res; + ul_sched_t ul_res; + }; + + srsran::circular_array, TTIMOD_SZ> results; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)), logger(srslog::fetch_basic_logger("MAC")) {} @@ -94,6 +153,7 @@ int sched_nr::cell_cfg(srsran::const_span cell_list) cfg.cells.emplace_back(cc, cell_list[cc], cfg.sched_cfg); } + pending_results.reset(new sched_result_manager(cell_list.size())); sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg)); return SRSRAN_SUCCESS; } @@ -113,33 +173,50 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) } } -void sched_nr::slot_indication(tti_point tti_rx) -{ - // Lock slot workers for provided tti_rx - sched_workers->reserve_workers(tti_rx); - - { - // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback - std::lock_guard lock(ue_db_mutex); - // Process pending events - pending_events->new_tti(); - - sched_workers->start_tti(tti_rx); - } -} - /// Generate {tti,cc} scheduling decision -int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& req) +int sched_nr::generate_slot_result(tti_point pdcch_tti, uint32_t cc) { + tti_point tti_rx = pdcch_tti - TX_ENB_DELAY; + + // Lock carrier workers for provided tti_rx + sched_workers->start_slot(tti_rx, [this]() { + // In case it is first worker for the given slot + // synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback + pending_events->new_slot(); + }); + // unlocked, parallel region - bool all_workers_finished = sched_workers->run_tti(tti_rx, cc, req); + bool all_workers_finished = sched_workers->run_slot(tti_rx, cc); if (all_workers_finished) { // once all workers of the same subframe finished, synchronize sched outcome with ue_db - std::lock_guard lock(ue_db_mutex); - sched_workers->end_tti(tti_rx); + sched_workers->release_slot(tti_rx); } + // Copy results to intermediate buffer + dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); + ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); + sched_workers->get_sched_result(pdcch_tti, cc, dl_res, ul_res); + + return SRSRAN_SUCCESS; +} + +int sched_nr::get_dl_sched(tti_point tti_tx, uint32_t cc, dl_sched_t& result) +{ + if (not pending_results->has_dl_result(tti_tx, cc)) { + generate_slot_result(tti_tx, cc); + } + + result = pending_results->pop_dl_result(tti_tx, cc); + return SRSRAN_SUCCESS; +} +int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) +{ + if (not pending_results->has_ul_result(tti_rx, cc)) { + return SRSRAN_ERROR; + } + + result = pending_results->pop_ul_result(tti_rx, cc); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 298fcbfcd..526858bbd 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -19,8 +19,8 @@ namespace sched_nr_impl { coreset_region::coreset_region(const bwp_cfg_t& bwp_cfg_, uint32_t coreset_id_, uint32_t slot_idx_, - pdsch_list_t& dl_list_, - pusch_list_t& ul_list_) : + pdcch_dl_list_t& dl_list_, + pdcch_ul_list_t& ul_list_) : bwp_cfg(&bwp_cfg_), coreset_cfg(&bwp_cfg_.coresets[coreset_id_ - 1].value()), coreset_id(coreset_id_), @@ -156,10 +156,10 @@ bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_d alloc_dfs.push_back(node); // set new DCI position if (record.alloc_type == pdcch_grant_type_t::ul_data) { - pusch_grant& pdcch_ul = pdcch_ul_list[record.idx]; + pdcch_ul_t& pdcch_ul = pdcch_ul_list[record.idx]; pdcch_ul.dci.ctx.location = node.dci_pos; } else { - pdsch_grant& pdcch_dl = pdcch_dl_list[record.idx]; + pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx]; pdcch_dl.dci.ctx.location = node.dci_pos; } return true; diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index f0a433c26..cd70a26ed 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -27,7 +27,7 @@ bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_ is_ul(srsran_tdd_nr_is_ul(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) { const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported - coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdschs, puschs); + coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, dl_pdcchs, ul_pdcchs); } void bwp_slot_grid::reset() @@ -37,15 +37,15 @@ void bwp_slot_grid::reset() } dl_rbgs.reset(); ul_rbgs.reset(); - pdschs.clear(); - puschs.clear(); + dl_pdcchs.clear(); + ul_pdcchs.clear(); pucchs.clear(); } bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_), cell_cfg(&cell_cfg_) { - for (uint32_t sl = 0; sl < SCHED_NR_NOF_SUBFRAMES; ++sl) { - slots.emplace_back(cell_cfg_, bwp_id, sl); + for (uint32_t sl = 0; sl < slots.capacity(); ++sl) { + slots.emplace_back(cell_cfg_, bwp_id, sl % static_cast(SRSRAN_NSLOTS_PER_FRAME_NR(0u))); } } @@ -75,7 +75,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx); return alloc_result::no_sch_space; } - pdsch_list_t& pdsch_grants = bwp_pdsch_slot.pdschs; + pdcch_dl_list_t& pdsch_grants = bwp_pdsch_slot.dl_pdcchs; if (pdsch_grants.full()) { logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; @@ -109,7 +109,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) } // Allocation Successful - pdsch_grant& pdcch = bwp_pdcch_slot.pdschs.back(); + pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); fill_dci_ue_cfg(ue, dl_mask, bwp_grid.cell_params(), pdcch.dci); pdsch_mask |= dl_mask; bwp_uci_slot.pucchs.emplace_back(); @@ -127,13 +127,14 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; } + auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti]; auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti]; if (not bwp_pusch_slot.is_ul) { logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx); return alloc_result::no_sch_space; } - pusch_list& pusch_grants = bwp_pusch_slot.puschs; - if (pusch_grants.full()) { + pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.ul_pdcchs; + if (pdcchs.full()) { logger.warning("SCHED: Maximum number of UL allocations reached"); return alloc_result::no_grant_space; } @@ -142,7 +143,7 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) return alloc_result::sch_collision; } const uint32_t aggr_idx = 2, coreset_id = 0; - if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { + if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -159,8 +160,8 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) } // Allocation Successful - pdsch_grant& pdsch = bwp_grid[ue.pdcch_tti].pdschs.back(); - fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdsch.dci); + pdcch_ul_t& pdcch = pdcchs.back(); + fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdcch.dci); pusch_mask |= ul_mask; return alloc_result::success; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index ab3b63d5c..f07fa9368 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -103,7 +103,6 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { slot_ctxts[i].reset(new slot_worker_ctxt()); - sem_init(&slot_ctxts[i]->sf_sem, 0, 1); slot_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]); @@ -111,44 +110,47 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& } } -sched_worker_manager::~sched_worker_manager() -{ - // acquire all slot worker contexts - for (auto& slot_ctxt : slot_ctxts) { - sem_wait(&slot_ctxt->sf_sem); - } - // destroy all slot worker contexts - for (auto& slot_ctxt : slot_ctxts) { - sem_destroy(&slot_ctxt->sf_sem); - } -} +sched_worker_manager::~sched_worker_manager() = default; sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) { return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()]; } -void sched_worker_manager::reserve_workers(tti_point tti_rx_) +void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback process_feedback) { - // lock if slot worker is already being used - auto& sf_worker_ctxt = get_sf(tti_rx_); - sem_wait(&sf_worker_ctxt.sf_sem); + auto& sf_worker_ctxt = get_sf(tti_rx); - sf_worker_ctxt.tti_rx = tti_rx_; + std::unique_lock lock(sf_worker_ctxt.slot_mutex); + while ((sf_worker_ctxt.tti_rx.is_valid() and sf_worker_ctxt.tti_rx != tti_rx)) { + // wait for previous slot to finish + sf_worker_ctxt.nof_workers_waiting++; + sf_worker_ctxt.cvar.wait(lock); + sf_worker_ctxt.nof_workers_waiting--; + } + if (sf_worker_ctxt.tti_rx == tti_rx) { + // another worker with the same slot idx already started + return; + } + + { + std::lock_guard db_lock(ue_db_mutex); + + process_feedback(); + + for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { + sf_worker_ctxt.workers[cc].start(tti_rx, ue_db); + } + } + + sf_worker_ctxt.tti_rx = tti_rx; sf_worker_ctxt.worker_count.store(static_cast(sf_worker_ctxt.workers.size()), std::memory_order_relaxed); -} - -void sched_worker_manager::start_tti(tti_point tti_rx_) -{ - auto& sf_worker_ctxt = get_sf(tti_rx_); - srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); - - for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) { - sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx, ue_db); + if (sf_worker_ctxt.nof_workers_waiting > 0) { + sf_worker_ctxt.cvar.notify_all(); } } -bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& tti_req) +bool sched_worker_manager::run_slot(tti_point tti_rx_, uint32_t cc) { auto& sf_worker_ctxt = get_sf(tti_rx_); srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); @@ -156,15 +158,6 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t // Get {tti, cc} scheduling decision sf_worker_ctxt.workers[cc].run(); - // Copy requested TTI DL and UL sched result - tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.dl_res.pdschs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdschs; - cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].reset(); - tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY; - tti_req.ul_res.puschs = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].puschs; - tti_req.ul_res.pucchs = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pucchs; - cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].reset(); - // decrement the number of active workers int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1; srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)"); @@ -172,18 +165,45 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t return rem_workers == 0; } -void sched_worker_manager::end_tti(tti_point tti_rx_) +void sched_worker_manager::release_slot(tti_point tti_rx_) { auto& sf_worker_ctxt = get_sf(tti_rx_); srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments"); srsran_assert(sf_worker_ctxt.worker_count == 0, "invalid number of calls to run_tti(tti, cc)"); - // All the workers of the same TTI have finished. Synchronize scheduling decisions with UEs state - for (slot_cc_worker& worker : sf_worker_ctxt.workers) { - worker.end_tti(); + { + std::lock_guard lock(ue_db_mutex); + + // All the workers of the same slot have finished. Synchronize scheduling decisions with UEs state + for (slot_cc_worker& worker : sf_worker_ctxt.workers) { + worker.end_tti(); + } } - sem_post(&sf_worker_ctxt.sf_sem); + std::unique_lock lock(sf_worker_ctxt.slot_mutex); + sf_worker_ctxt.tti_rx = {}; + if (sf_worker_ctxt.nof_workers_waiting > 0) { + sf_worker_ctxt.cvar.notify_one(); + } +} + +bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) +{ + auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0][pdcch_tti]; + + dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs; + dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs; + + ul_res.pucch.resize(pdcch_bwp_slot.pucchs.size()); + for (uint32_t i = 0; i < pdcch_bwp_slot.pucchs.size(); ++i) { + ul_res.pucch[i].uci_cfg.pucch.rnti = pdcch_bwp_slot.pucchs[i].resource.rnti; + ul_res.pucch[i].uci_cfg.pucch.resource_id = pdcch_bwp_slot.pucchs[i].resource.resource_id; + } + + // clear up BWP slot + pdcch_bwp_slot.reset(); + + return true; } } // namespace sched_nr_impl diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index fa28063dd..8db2034e2 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -44,8 +44,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) { uint32_t cc = cc_out.cc; - for (uint32_t i = 0; i < cc_out.dl_cc_result->pdschs.size(); ++i) { - const auto& data = cc_out.dl_cc_result->pdschs[i]; + for (uint32_t i = 0; i < cc_out.dl_cc_result->pdcch_dl.size(); ++i) { + const auto& data = cc_out.dl_cc_result->pdcch_dl[i]; if (data.dci.ctx.rnti != ctxt.rnti) { continue; } @@ -98,7 +98,7 @@ int sched_nr_sim_base::add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_ return SRSRAN_SUCCESS; } -void sched_nr_sim_base::slot_indication(srsran::tti_point tti_rx) +void sched_nr_sim_base::new_slot(srsran::tti_point tti_rx) { { std::unique_lock lock(mutex); @@ -113,7 +113,6 @@ void sched_nr_sim_base::slot_indication(srsran::tti_point tti_rx) apply_tti_events(ue.second.get_ctxt(), events); } } - sched_ptr->slot_indication(tti_rx); } void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out) diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsenb/test/mac/nr/sched_nr_sim_ue.h index b6c8e5755..ccac6f2d0 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.h +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.h @@ -20,10 +20,10 @@ namespace srsenb { struct sched_nr_cc_output_res_t { - tti_point tti_rx; - uint32_t cc; - sched_nr_interface::dl_tti_request_t* dl_cc_result; - sched_nr_interface::ul_tti_request_t* ul_cc_result; + tti_point tti_rx; + uint32_t cc; + sched_nr_interface::dl_sched_t* dl_cc_result; + sched_nr_interface::ul_sched_t* ul_cc_result; }; struct ue_nr_cc_ctxt_t { @@ -75,7 +75,7 @@ public: int add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx); - void slot_indication(srsran::tti_point tti_rx); + void new_slot(srsran::tti_point tti_rx); void update(sched_nr_cc_output_res_t& cc_out); sched_nr_ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 2130df547..60f1924c1 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -17,6 +17,8 @@ namespace srsenb { +using dl_sched_t = sched_nr_interface::dl_sched_t; + srsran_coreset_t get_default_coreset() { srsran_coreset_t coreset{}; @@ -87,37 +89,46 @@ sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) } struct task_job_manager { - std::mutex mutex; - std::condition_variable cond_var; - int tasks = 0; - int res_count = 0; - int pdsch_count = 0; - int max_tasks = std::numeric_limits::max() / 2; - srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); + std::mutex mutex; + int res_count = 0; + int pdsch_count = 0; + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); + struct slot_guard { + int count = 0; + std::condition_variable cvar; + }; + srsran::bounded_vector slot_counter{}; - void start_task() + explicit task_job_manager(int max_concurrent_slots = 4) : slot_counter(max_concurrent_slots) {} + + void start_slot(tti_point tti, int nof_sectors) { std::unique_lock lock(mutex); - while (tasks >= max_tasks) { - cond_var.wait(lock); + auto& sl = slot_counter[tti.to_uint() % slot_counter.size()]; + while (sl.count > 0) { + sl.cvar.wait(lock); } - tasks++; + sl.count = nof_sectors; } - void finish_task(const sched_nr_interface::tti_request_t& res) + void finish_cc(tti_point tti, const dl_sched_t& dl_res, const sched_nr_interface::ul_sched_t& ul_res) { std::unique_lock lock(mutex); - TESTASSERT(res.dl_res.pdschs.size() <= 1); + TESTASSERT(dl_res.pdcch_dl.size() <= 1); res_count++; - pdsch_count += res.dl_res.pdschs.size(); - if (tasks-- >= max_tasks or tasks == 0) { - cond_var.notify_one(); + pdsch_count += dl_res.pdcch_dl.size(); + auto& sl = slot_counter[tti.to_uint() % slot_counter.size()]; + if (--sl.count == 0) { + sl.cvar.notify_one(); } } void wait_task_finish() { std::unique_lock lock(mutex); - while (tasks > 0) { - cond_var.wait(lock); + for (auto& sl : slot_counter) { + while (sl.count > 0) { + sl.cvar.wait(lock); + } + sl.count = 1; } } void print_results() const @@ -142,17 +153,19 @@ void sched_nr_cfg_serialized_test() sched_tester.add_user(0x46, uecfg, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { - tti_point tti(nof_ttis % 10240); - sched_tester.slot_indication(tti); + tti_point tti_rx(nof_ttis % 10240); + tti_point tti_tx = tti_rx + TX_ENB_DELAY; + tasks.start_slot(tti_rx, nof_sectors); + sched_tester.new_slot(tti_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - tasks.start_task(); - sched_nr_interface::tti_request_t res; - TESTASSERT(sched_tester.get_sched()->generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); - sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; + sched_nr_interface::dl_sched_t dl_res; + sched_nr_interface::ul_sched_t ul_res; + TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); + TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); + sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); - tasks.finish_task(res); - TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti + TX_ENB_DELAY).sf_idx()) or - res.dl_res.pdschs.size() == 1); + tasks.finish_cc(tti_rx, dl_res, ul_res); + TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti_tx).sf_idx()) or dl_res.pdcch_dl.size() == 1); } } @@ -162,11 +175,12 @@ void sched_nr_cfg_serialized_test() void sched_nr_cfg_parallel_cc_test() { + uint32_t nof_sectors = 4; uint32_t max_nof_ttis = 1000; task_job_manager tasks; sched_nr_interface::sched_cfg_t cfg; - std::vector cells_cfg = get_default_cells_cfg(4); + std::vector cells_cfg = get_default_cells_cfg(nof_sectors); sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); @@ -174,16 +188,19 @@ void sched_nr_cfg_parallel_cc_test() sched_tester.add_user(0x46, uecfg, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { - tti_point tti(nof_ttis % 10240); - sched_tester.slot_indication(tti); + tti_point tti_rx(nof_ttis % 10240); + tti_point tti_tx = tti_rx + TX_ENB_DELAY; + tasks.start_slot(tti_tx, nof_sectors); + sched_tester.new_slot(tti_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - tasks.start_task(); - srsran::get_background_workers().push_task([cc, tti, &tasks, &sched_tester]() { - sched_nr_interface::tti_request_t res; - TESTASSERT(sched_tester.get_sched()->generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); - sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res}; + srsran::get_background_workers().push_task([cc, tti_tx, &tasks, &sched_tester]() { + sched_nr_interface::dl_sched_t dl_res; + sched_nr_interface::ul_sched_t ul_res; + TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); + TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); + sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); - tasks.finish_task(res); + tasks.finish_cc(tti_tx, dl_res, ul_res); }); } } @@ -191,6 +208,7 @@ void sched_nr_cfg_parallel_cc_test() tasks.wait_task_finish(); tasks.print_results(); + TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); } void sched_nr_cfg_parallel_sf_test() @@ -211,13 +229,14 @@ void sched_nr_cfg_parallel_sf_test() for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); - sched.slot_indication(tti); + tasks.start_slot(tti, nof_sectors); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - tasks.start_task(); srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { - sched_nr_interface::tti_request_t res; - TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); - tasks.finish_task(res); + sched_nr_interface::dl_sched_t dl_res; + sched_nr_interface::ul_sched_t ul_res; + TESTASSERT(sched.get_dl_sched(tti, cc, dl_res) == SRSRAN_SUCCESS); + TESTASSERT(sched.get_ul_sched(tti, cc, ul_res) == SRSRAN_SUCCESS); + tasks.finish_cc(tti, dl_res, ul_res); }); } } From 2db8b8d87636daabcbc721bc2e8e25ede315f3d0 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 6 Jul 2021 18:16:04 +0100 Subject: [PATCH 51/59] sched,nr: add RAR scheduler inspired in LTE one --- srsenb/hdr/stack/mac/nr/sched_nr.h | 6 +- srsenb/hdr/stack/mac/nr/sched_nr_bwp.h | 79 +++++++++ srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 84 +++++----- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 21 ++- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 2 +- ...{sched_nr_phy_helpers.h => sched_nr_phy.h} | 16 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 30 ++-- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 14 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 3 +- srsenb/src/stack/mac/nr/sched_nr.cc | 1 + srsenb/src/stack/mac/nr/sched_nr_bwp.cc | 157 ++++++++++++++++++ srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 1 + ...ched_nr_phy_helpers.cc => sched_nr_phy.cc} | 34 +++- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 72 ++++++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 30 ++-- 15 files changed, 456 insertions(+), 94 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_bwp.h rename srsenb/hdr/stack/mac/nr/{sched_nr_phy_helpers.h => sched_nr_phy.h} (70%) create mode 100644 srsenb/src/stack/mac/nr/sched_nr_bwp.cc rename srsenb/src/stack/mac/nr/{sched_nr_phy_helpers.cc => sched_nr_phy.cc} (84%) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 4a0cbf4ea..e288098da 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -27,7 +27,8 @@ namespace srsenb { namespace sched_nr_impl { class sched_worker_manager; -} +class cell_sched; +} // namespace sched_nr_impl class ue_event_manager; class sched_result_manager; @@ -66,6 +67,9 @@ private: // management of Sched Result buffering std::unique_ptr pending_results; + + // management of cell resources + std::vector > cells; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h new file mode 100644 index 000000000..79fdb4fb9 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h @@ -0,0 +1,79 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_BWP_H +#define SRSRAN_SCHED_NR_BWP_H + +#include "sched_nr_cfg.h" +#include "sched_nr_rb_grid.h" +#include "srsran/adt/pool/cached_alloc.h" + +namespace srsenb { +namespace sched_nr_impl { + +using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t; + +struct pending_rar_t { + uint16_t ra_rnti = 0; + tti_point prach_tti; + srsran::bounded_vector msg3_grant; +}; + +/// RAR/Msg3 scheduler +class ra_sched +{ +public: + explicit ra_sched(const sched_cell_params& cell_cfg_); + + int dl_rach_info(const dl_sched_rar_info_t& rar_info); + void run_slot(bwp_slot_allocator& slot_grid); + size_t empty() const { return pending_rars.empty(); } + +private: + alloc_result + allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc); + + const sched_cell_params* cell_cfg = nullptr; + srslog::basic_logger& logger; + + srsran::deque pending_rars; +}; + +class bwp_sched +{ +public: + explicit bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); + + const sched_cell_params* cell_cfg; + const uint32_t bwp_id; + + // channel-specific schedulers + ra_sched ra; + + // Pending allocations + bwp_res_grid grid; +}; + +class cell_sched +{ +public: + srsran::bounded_vector bwps; + + explicit cell_sched(const sched_cell_params& cell_cfg_); + + const sched_cell_params* cfg; +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_BWP_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 1bcf2d9ae..c12dd70af 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -33,6 +33,7 @@ using pucch_list_t = sched_nr_interface::pucch_list_t; using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; struct sched_cell_params { const uint32_t cc; @@ -49,8 +50,51 @@ struct sched_params { explicit sched_params(const sched_cfg_t& sched_cfg_); }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using rbgmask_t = srsran::bounded_bitset; + using pdcchmask_t = srsran::bounded_bitset; -using rbgmask_t = srsran::bounded_bitset; + +using pdcch_cce_pos_list = srsran::bounded_vector; +using bwp_cce_pos_list = std::array, SRSRAN_NOF_SF_X_FRAME>; +void get_dci_locs(const srsran_coreset_t& coreset, + const srsran_search_space_t& search_space, + uint16_t rnti, + bwp_cce_pos_list& cce_locs); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using ue_cfg_t = sched_nr_interface::ue_cfg_t; +using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; + +class ue_cfg_extended : public ue_cfg_t +{ +public: + struct search_space_params { + srsran_search_space_t* cfg = nullptr; + }; + struct coreset_params { + srsran_coreset_t* cfg = nullptr; + std::vector ss_list; + bwp_cce_pos_list cce_positions; + }; + struct bwp_params { + std::vector search_spaces; + std::vector coresets; + }; + struct cc_params { + srsran::bounded_vector bwps; + }; + + uint16_t rnti; + std::vector cc_params; + + ue_cfg_extended() = default; + explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct resource_guard { public: @@ -92,44 +136,6 @@ private: bool flag = false; }; -using pdcch_cce_pos_list = srsran::bounded_vector; -using bwp_cce_pos_list = std::array, SRSRAN_NOF_SF_X_FRAME>; -void get_dci_locs(const srsran_coreset_t& coreset, - const srsran_search_space_t& search_space, - uint16_t rnti, - bwp_cce_pos_list& cce_locs); - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -using ue_cfg_t = sched_nr_interface::ue_cfg_t; -using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; - -class ue_cfg_extended : public ue_cfg_t -{ -public: - struct search_space_params { - srsran_search_space_t* cfg = nullptr; - }; - struct coreset_params { - srsran_coreset_t* cfg = nullptr; - std::vector ss_list; - bwp_cce_pos_list cce_positions; - }; - struct bwp_params { - std::vector search_spaces; - std::vector coresets; - }; - struct cc_params { - srsran::bounded_vector bwps; - }; - - uint16_t rnti; - std::vector cc_params; - - ue_cfg_extended() = default; - explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); -}; - } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 2b82bf83e..4060766b5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -26,7 +26,7 @@ namespace srsenb { const static size_t SCHED_NR_MAX_CARRIERS = 4; const static uint16_t SCHED_NR_INVALID_RNTI = 0; -const static size_t SCHED_NR_MAX_NOF_RBGS = 25; +const static size_t SCHED_NR_MAX_NOF_RBGS = 17; const static size_t SCHED_NR_MAX_TB = 1; const static size_t SCHED_NR_MAX_HARQ = 16; const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; @@ -52,14 +52,17 @@ public: using pusch_td_res_alloc_list = srsran::bounded_vector; struct bwp_cfg_t { - uint32_t bwp_id = 1; - uint32_t start_rb = 0; - uint32_t rb_width = 100; + uint32_t bwp_id = 1; + uint32_t start_rb = 0; + uint32_t rb_width = 100; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; std::array, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets; }; struct cell_cfg_t { + uint32_t rar_window_size; uint32_t nof_prb = 100; uint32_t nof_rbg = 25; srsran_tdd_config_nr_t tdd = {}; @@ -82,6 +85,16 @@ public: srsran::phy_cfg_nr_t phy_cfg = {}; }; + ////// RACH ////// + + struct dl_sched_rar_info_t { + uint32_t preamble_idx; + uint32_t ta_cmd; + uint16_t temp_crnti; + uint32_t msg3_size; + uint32_t prach_tti; + }; + ///// Sched Result ///// using dl_sched_t = mac_interface_phy_nr::dl_sched_t; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index f7fe40bda..ba39e671b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -25,7 +25,7 @@ namespace sched_nr_impl { using coreset_bitmap = srsran::bounded_bitset; -enum class pdcch_grant_type_t { sib, dl_data, ul_data }; +enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data }; class slot_ue; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h similarity index 70% rename from srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h rename to srsenb/hdr/stack/mac/nr/sched_nr_phy.h index 071d779f3..ac032bcdf 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H -#define SRSRAN_SCHED_NR_PHY_HELPERS_H +#ifndef SRSRAN_SCHED_NR_PHY_H +#define SRSRAN_SCHED_NR_PHY_H #include "sched_nr_cfg.h" @@ -21,6 +21,16 @@ namespace sched_nr_impl { uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); +using pdsch_bitmap = srsran::bounded_bitset; +using pusch_bitmap = srsran::bounded_bitset; +using rbg_interval = srsran::interval; + +rbg_interval find_empty_rbg_interval(const pdsch_bitmap& bitmap, uint32_t max_nof_rbgs); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci); + class slot_ue; void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, @@ -44,4 +54,4 @@ pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbg } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H +#endif // SRSRAN_SCHED_NR_PHY_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 92a15f54c..a925aaf35 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -17,13 +17,15 @@ #include "lib/include/srsran/adt/circular_array.h" #include "sched_nr_interface.h" #include "sched_nr_pdcch.h" +#include "sched_nr_phy.h" #include "sched_nr_ue.h" namespace srsenb { namespace sched_nr_impl { -using pdsch_bitmap = srsran::bounded_bitset<25, true>; -using pusch_bitmap = srsran::bounded_bitset<25, true>; +struct pending_rar_t; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; @@ -54,35 +56,35 @@ struct bwp_res_grid { const sched_cell_params& cell_params() const { return *cell_cfg; } const bwp_cfg_t& bwp_cfg() const { return cell_cfg->cell_cfg.bwps[id() - 1]; } -private: - uint32_t bwp_id; const sched_cell_params* cell_cfg = nullptr; +private: + uint32_t bwp_id; + srsran::bounded_vector slots; }; -struct cell_res_grid { - const sched_cell_params* cell_cfg = nullptr; - srsran::bounded_vector bwps; - - explicit cell_res_grid(const sched_cell_params& cell_cfg); -}; - -class slot_bwp_sched +class bwp_slot_allocator { public: - explicit slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_); + explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_); + void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; } + + alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, rbg_interval interv, uint32_t max_nof_grants); alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); + tti_point get_pdcch_tti() const { return pdcch_tti; } + const bwp_res_grid& res_grid() const { return bwp_grid; } + const sched_cell_params& cfg; private: srslog::basic_logger& logger; bwp_res_grid& bwp_grid; - tti_point tti_rx; + tti_point pdcch_tti; }; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 0b4d4c45f..86c2af5ed 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_SCHED_NR_WORKER_H #define SRSRAN_SCHED_NR_WORKER_H +#include "sched_nr_bwp.h" #include "sched_nr_cfg.h" #include "sched_nr_rb_grid.h" #include "sched_nr_ue.h" @@ -32,9 +33,7 @@ using ul_sched_t = sched_nr_interface::ul_sched_t; class slot_cc_worker { public: - explicit slot_cc_worker(const sched_cell_params& cell_params, cell_res_grid& phy_grid) : - cfg(cell_params), res_grid(0, phy_grid) - {} + explicit slot_cc_worker(cell_sched& sched); void start(tti_point tti_rx_, ue_map_t& ue_db_); void run(); @@ -46,9 +45,10 @@ private: void alloc_ul_ues(); const sched_cell_params& cfg; + cell_sched& cell; - tti_point tti_rx; - slot_bwp_sched res_grid; + tti_point tti_rx; + bwp_slot_allocator bwp_alloc; srsran::static_circular_map slot_ues; }; @@ -80,9 +80,9 @@ private: ue_map_t& ue_db; std::mutex ue_db_mutex; - std::vector > slot_ctxts; + std::vector > slot_worker_ctxts; - srsran::bounded_vector cell_grid_list; + srsran::bounded_vector cell_grid_list; slot_worker_ctxt& get_sf(tti_point tti_rx); }; diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 2f18bc2c3..d91ec20ae 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,7 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy_helpers.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc + sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index bd9022ff2..c25ca4bfe 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsran/common/thread_pool.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc new file mode 100644 index 000000000..ac59dcbd9 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -0,0 +1,157 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsran/common/standard_streams.h" +#include "srsran/common/string_helpers.h" + +namespace srsenb { +namespace sched_nr_impl { + +ra_sched::ra_sched(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_), logger(srslog::fetch_basic_logger("MAC")) +{} + +alloc_result +ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) +{ + const uint32_t rar_aggr_level = 2; + auto& pdsch_bitmap = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_rbgs; + + alloc_result ret = alloc_result::other_cause; + for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { + ret = alloc_result::invalid_coderate; + for (uint32_t nrbg = 1; nrbg < cell_cfg->cell_cfg.nof_rbg and ret == alloc_result::invalid_coderate; ++nrbg) { + rbg_interval rbg_interv = find_empty_rbg_interval(pdsch_bitmap, nrbg); + if (rbg_interv.length() == nrbg) { + ret = slot_grid.alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc); + } else { + ret = alloc_result::no_sch_space; + } + } + + // If allocation was not successful because there were not enough RBGs, try allocating fewer Msg3 grants + if (ret != alloc_result::invalid_coderate and ret != alloc_result::no_sch_space) { + break; + } + } + if (ret != alloc_result::success) { + logger.info("SCHED: RAR allocation for L=%d was postponed. Cause=%s", rar_aggr_level, to_string(ret)); + } + return ret; +} + +void ra_sched::run_slot(bwp_slot_allocator& slot_grid) +{ + static const uint32_t PRACH_RAR_OFFSET = 3; + tti_point pdcch_tti = slot_grid.get_pdcch_tti(); + + for (auto it = pending_rars.begin(); it != pending_rars.end();) { + pending_rar_t& rar = *it; + + // In case of RAR outside RAR window: + // - if window has passed, discard RAR + // - if window hasn't started, stop loop, as RARs are ordered by TTI + tti_interval rar_window{rar.prach_tti + PRACH_RAR_OFFSET, + rar.prach_tti + PRACH_RAR_OFFSET + cell_cfg->cell_cfg.rar_window_size}; + if (not rar_window.contains(pdcch_tti)) { + if (pdcch_tti >= rar_window.stop()) { + fmt::memory_buffer str_buffer; + fmt::format_to(str_buffer, + "SCHED: Could not transmit RAR within the window (RA={}, Window={}, RAR={}", + rar.prach_tti, + rar_window, + pdcch_tti); + srsran::console("%s\n", srsran::to_c_str(str_buffer)); + logger.warning("%s", srsran::to_c_str(str_buffer)); + it = pending_rars.erase(it); + continue; + } + return; + } + + // Try to schedule DCI + RBGs for RAR Grant + uint32_t nof_rar_allocs = 0; + alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs); + + if (ret == alloc_result::success) { + // If RAR allocation was successful: + // - in case all Msg3 grants were allocated, remove pending RAR, and continue with following RAR + // - otherwise, erase only Msg3 grants that were allocated, and stop iteration + + if (nof_rar_allocs == rar.msg3_grant.size()) { + it = pending_rars.erase(it); + } else { + std::copy(rar.msg3_grant.begin() + nof_rar_allocs, rar.msg3_grant.end(), rar.msg3_grant.begin()); + rar.msg3_grant.resize(rar.msg3_grant.size() - nof_rar_allocs); + break; + } + } else { + // If RAR allocation was not successful: + // - in case of unavailable PDCCH space, try next pending RAR allocation + // - otherwise, stop iteration + if (ret != alloc_result::no_cch_space) { + break; + } + ++it; + } + } +} + +int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) +{ + logger.info("SCHED: New PRACH tti=%d, preamble=%d, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d", + rar_info.prach_tti, + rar_info.preamble_idx, + rar_info.temp_crnti, + rar_info.ta_cmd, + rar_info.msg3_size); + + // RA-RNTI = 1 + t_id + f_id + // t_id = index of first subframe specified by PRACH (0<=t_id<10) + // f_id = index of the PRACH within subframe, in ascending order of freq domain (0<=f_id<6) (for FDD, f_id=0) + uint16_t ra_rnti = 1 + (uint16_t)(rar_info.prach_tti % 10u); + + // find pending rar with same RA-RNTI + for (pending_rar_t& r : pending_rars) { + if (r.prach_tti.to_uint() == rar_info.prach_tti and ra_rnti == r.ra_rnti) { + if (r.msg3_grant.size() >= sched_interface::MAX_RAR_LIST) { + logger.warning("PRACH ignored, as the the maximum number of RAR grants per tti has been reached"); + return SRSRAN_ERROR; + } + r.msg3_grant.push_back(rar_info); + return SRSRAN_SUCCESS; + } + } + + // create new RAR + pending_rar_t p; + p.ra_rnti = ra_rnti; + p.prach_tti = tti_point{rar_info.prach_tti}; + p.msg3_grant.push_back(rar_info); + pending_rars.push_back(p); + + return SRSRAN_SUCCESS; +} + +bwp_sched::bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : + cell_cfg(&cell_cfg_), bwp_id(bwp_id_), ra(cell_cfg_), grid(cell_cfg_, bwp_id_) +{} + +cell_sched::cell_sched(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) +{ + for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { + bwps.emplace_back(cell_cfg_, bwp_id); + } +} + +} // namespace sched_nr_impl +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index ce61367c5..99fe100ba 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy.cc similarity index 84% rename from srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc rename to srsenb/src/stack/mac/nr/sched_nr_phy.cc index 779f7c041..e8403abe0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" @@ -82,6 +82,38 @@ int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb) return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length()); } +rbg_interval find_empty_rbg_interval(const pdsch_bitmap& in_mask, uint32_t max_size) +{ + rbg_interval max_interv; + + for (size_t n = 0; n < in_mask.size();) { + int pos = in_mask.find_lowest(n, in_mask.size(), false); + if (pos < 0) { + break; + } + + size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size); + int pos2 = in_mask.find_lowest(pos + 1, max_pos, true); + rbg_interval interv(pos, pos2 < 0 ? max_pos : pos2); + if (interv.length() >= max_size) { + return interv; + } + if (interv.length() > max_interv.length()) { + max_interv = interv; + } + n = interv.stop(); + } + return max_interv; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci) +{ + dci.mcs = 5; + return true; +} + template void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index cd70a26ed..57a0a0caa 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -11,7 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" namespace srsenb { namespace sched_nr_impl { @@ -49,20 +49,68 @@ bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) } } -cell_res_grid::cell_res_grid(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_) -{ - for (uint32_t bwp_id = 0; bwp_id < cell_cfg->cell_cfg.bwps.size(); ++bwp_id) { - bwps.emplace_back(cell_cfg_, bwp_id); - } -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -slot_bwp_sched::slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_) : - logger(srslog::fetch_basic_logger("MAC")), cfg(*phy_grid_.cell_cfg), bwp_grid(phy_grid_.bwps[bwp_id]) +bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : + logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cell_cfg), bwp_grid(bwp_grid_) {} -alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx, + const srsenb::sched_nr_impl::pending_rar_t& rar, + srsenb::sched_nr_impl::rbg_interval interv, + uint32_t nof_grants) +{ + static const uint32_t msg3_nof_prbs = 3; + + bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti]; + bwp_slot_grid& bwp_msg3_slot = bwp_grid[pdcch_tti + 4]; + + if (bwp_pdcch_slot.dl_pdcchs.full()) { + logger.warning("SCHED: Maximum number of DL allocations reached"); + return alloc_result::no_grant_space; + } + + // Check DL RB collision + rbgmask_t& pdsch_mask = bwp_pdcch_slot.dl_rbgs; + rbgmask_t dl_mask(pdsch_mask.size()); + dl_mask.fill(interv.start(), interv.stop()); + if ((pdsch_mask & dl_mask).any()) { + logger.debug("SCHED: Provided RBG mask collides with allocation previously made."); + return alloc_result::sch_collision; + } + + // Check Msg3 RB collision + uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants; + uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.bwp_cfg().rb_width, false)); + rbg_interval msg3_rbgs = find_empty_rbg_interval(bwp_msg3_slot.ul_rbgs, total_ul_nof_rbgs); + if (msg3_rbgs.length() < total_ul_nof_rbgs) { + logger.debug("SCHED: No space in PUSCH for Msg3."); + return alloc_result::sch_collision; + } + + // Find PDCCH position + const uint32_t coreset_id = 0; + if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::rar, aggr_idx, nullptr)) { + // Could not find space in PDCCH + logger.debug("SCHED: No space in PDCCH for DL tx."); + return alloc_result::no_cch_space; + } + + // Generate DCI for RAR + pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); + if (not fill_dci_rar(interv, bwp_grid.cell_params(), pdcch.dci)) { + // Cancel on-going PDCCH allocation + bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); + return alloc_result::invalid_coderate; + } + + // RAR allocation successful. + bwp_pdcch_slot.dl_rbgs.fill(interv.start(), interv.stop()); + + return alloc_result::success; +} + +alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) { if (ue.h_dl == nullptr) { logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); @@ -121,7 +169,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) return alloc_result::success; } -alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) { if (ue.h_ul == nullptr) { logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index f07fa9368..2895ada6b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -15,6 +15,10 @@ namespace srsenb { namespace sched_nr_impl { +slot_cc_worker::slot_cc_worker(cell_sched& cc_sched) : + cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid) +{} + /// Called at the beginning of TTI in a locked context, to reserve available UE resources void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) { @@ -34,15 +38,18 @@ void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) } // UE acquired successfully for scheduling in this {tti, cc} } - - tti_rx = tti_rx_; } void slot_cc_worker::run() { srsran_assert(running(), "scheduler worker::run() called for non-active worker"); - // Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion + bwp_alloc.new_slot(tti_rx + TX_ENB_DELAY); + + // Allocate pending RARs + cell.bwps[0].ra.run_slot(bwp_alloc); + + // Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion if ((tti_rx.to_uint() & 0x1u) == 0) { alloc_dl_ues(); alloc_ul_ues(); @@ -74,8 +81,9 @@ void slot_cc_worker::alloc_dl_ues() rbgmask_t dlmask(cfg.cell_cfg.nof_rbg); dlmask.fill(0, dlmask.size(), true); - res_grid.alloc_pdsch(ue, dlmask); + bwp_alloc.alloc_pdsch(ue, dlmask); } + void slot_cc_worker::alloc_ul_ues() { if (slot_ues.empty()) { @@ -88,7 +96,7 @@ void slot_cc_worker::alloc_ul_ues() rbgmask_t ulmask(cfg.cell_cfg.nof_rbg); ulmask.fill(0, ulmask.size(), true); - res_grid.alloc_pusch(ue, ulmask); + bwp_alloc.alloc_pusch(ue, ulmask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -100,12 +108,12 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& } // Note: For now, we only allow parallelism at the sector level - slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); + slot_worker_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { - slot_ctxts[i].reset(new slot_worker_ctxt()); - slot_ctxts[i]->workers.reserve(cfg.cells.size()); + slot_worker_ctxts[i].reset(new slot_worker_ctxt()); + slot_worker_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]); + slot_worker_ctxts[i]->workers.emplace_back(cell_grid_list[cc]); } } } @@ -114,7 +122,7 @@ sched_worker_manager::~sched_worker_manager() = default; sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) { - return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()]; + return *slot_worker_ctxts[tti_rx.to_uint() % slot_worker_ctxts.size()]; } void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback process_feedback) @@ -189,7 +197,7 @@ void sched_worker_manager::release_slot(tti_point tti_rx_) bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) { - auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0][pdcch_tti]; + auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti]; dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs; dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs; From dd3c9b4d7e4c835d73da4beeb7c8473bfc4fb198 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 7 Jul 2021 14:40:29 +0100 Subject: [PATCH 52/59] sched,nr: utilization of common bwp params structure across multiple sched objects --- srsenb/hdr/stack/mac/nr/sched_nr.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_bwp.h | 21 +++++----- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 19 ++++++++- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 20 ++++----- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 12 +++--- srsenb/hdr/stack/mac/nr/sched_nr_phy.h | 22 +++------- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 23 +++++------ srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 6 +-- srsenb/src/stack/mac/nr/sched_nr_bwp.cc | 15 +++---- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 16 +++++++- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 16 ++++---- srsenb/src/stack/mac/nr/sched_nr_phy.cc | 43 ++++++++------------ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 30 +++++++------- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 6 +-- srsenb/test/mac/nr/sched_nr_test.cc | 4 +- 15 files changed, 124 insertions(+), 133 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index e288098da..d99b702ca 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -27,7 +27,7 @@ namespace srsenb { namespace sched_nr_impl { class sched_worker_manager; -class cell_sched; +class serv_cell_ctxt; } // namespace sched_nr_impl class ue_event_manager; @@ -69,7 +69,7 @@ private: std::unique_ptr pending_results; // management of cell resources - std::vector > cells; + std::vector > cells; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h index 79fdb4fb9..252ee6f26 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h @@ -32,7 +32,7 @@ struct pending_rar_t { class ra_sched { public: - explicit ra_sched(const sched_cell_params& cell_cfg_); + explicit ra_sched(const bwp_params& bwp_cfg_); int dl_rach_info(const dl_sched_rar_info_t& rar_info); void run_slot(bwp_slot_allocator& slot_grid); @@ -42,33 +42,32 @@ private: alloc_result allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc); - const sched_cell_params* cell_cfg = nullptr; - srslog::basic_logger& logger; + const bwp_params* bwp_cfg = nullptr; + srslog::basic_logger& logger; srsran::deque pending_rars; }; -class bwp_sched +class bwp_ctxt { public: - explicit bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); + explicit bwp_ctxt(const bwp_params& bwp_cfg); - const sched_cell_params* cell_cfg; - const uint32_t bwp_id; + const bwp_params* cfg; // channel-specific schedulers ra_sched ra; - // Pending allocations + // Stores pending allocations and PRB bitmaps bwp_res_grid grid; }; -class cell_sched +class serv_cell_ctxt { public: - srsran::bounded_vector bwps; + srsran::bounded_vector bwps; - explicit cell_sched(const sched_cell_params& cell_cfg_); + explicit serv_cell_ctxt(const sched_cell_params& cell_cfg_); const sched_cell_params* cfg; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index c12dd70af..0e78bae23 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -35,11 +35,26 @@ using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; -struct sched_cell_params { +struct bwp_params { + const uint32_t bwp_id; const uint32_t cc; - const cell_cfg_t cell_cfg; + const bwp_cfg_t& cfg; + const cell_cfg_t& cell_cfg; const sched_cfg_t& sched_cfg; + // derived params + uint32_t P; + uint32_t N_rbg; + + bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); +}; + +struct sched_cell_params { + const uint32_t cc; + const cell_cfg_t cell_cfg; + const sched_cfg_t& sched_cfg; + std::vector bwps; + sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_); }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 4060766b5..164b837f9 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -34,9 +34,6 @@ const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; class sched_nr_interface { public: - using pdcch_bitmap = srsran::bounded_bitset; - using rbg_bitmap = srsran::bounded_bitset; - static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS; ///// Configuration ///// @@ -52,21 +49,18 @@ public: using pusch_td_res_alloc_list = srsran::bounded_vector; struct bwp_cfg_t { - uint32_t bwp_id = 1; - uint32_t start_rb = 0; - uint32_t rb_width = 100; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; + uint32_t start_rb = 0; + uint32_t rb_width = 100; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + uint32_t rar_window_size = 3; std::array, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets; }; struct cell_cfg_t { - uint32_t rar_window_size; - uint32_t nof_prb = 100; - uint32_t nof_rbg = 25; - srsran_tdd_config_nr_t tdd = {}; - srsran::bounded_vector bwps{1}; + srsran_tdd_config_nr_t tdd = {}; + srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; struct sched_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index ba39e671b..60d4c2772 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -38,11 +38,11 @@ using pdcch_ul_list_t = srsran::bounded_vector; class coreset_region { public: - coreset_region(const bwp_cfg_t& bwp_cfg_, - uint32_t coreset_id_, - uint32_t slot_idx, - pdcch_dl_list_t& pdcch_dl_list, - pdcch_ul_list_t& pdcch_ul_list); + coreset_region(const bwp_params& bwp_cfg_, + uint32_t coreset_id_, + uint32_t slot_idx, + pdcch_dl_list_t& pdcch_dl_list, + pdcch_ul_list_t& pdcch_ul_list); void reset(); /** @@ -62,7 +62,7 @@ public: size_t nof_allocs() const { return dfs_tree.size(); } private: - const bwp_cfg_t* bwp_cfg; + const bwp_params* bwp_cfg; const srsran_coreset_t* coreset_cfg; uint32_t coreset_id; uint32_t slot_idx; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h index ac032bcdf..549310e19 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h @@ -29,25 +29,13 @@ rbg_interval find_empty_rbg_interval(const pdsch_bitmap& bitmap, uint32_t max_no /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci); +bool fill_dci_rar(rbg_interval rbginterv, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci); class slot_ue; -void fill_dci_ue_cfg(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_dci_dl_nr_t& dci); -void fill_dci_ue_cfg(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_dci_ul_nr_t& dci); -void fill_pdsch_ue(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch); -void fill_pusch_ue(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch); +void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci); +void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_ul_nr_t& dci); +void fill_pdsch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_sch_cfg_nr_t& sch); +void fill_pusch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_sch_cfg_nr_t& sch); pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index a925aaf35..0a8dbf98f 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -31,8 +31,9 @@ const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; struct bwp_slot_grid { - uint32_t bwp_id; uint32_t slot_idx; + const bwp_params* cfg; + bool is_dl, is_ul; pdsch_bitmap dl_rbgs; pusch_bitmap ul_rbgs; @@ -42,25 +43,21 @@ struct bwp_slot_grid { pucch_list_t pucchs; bwp_slot_grid() = default; - explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_); + explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); void reset(); }; struct bwp_res_grid { - bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); + bwp_res_grid(const bwp_params& bwp_cfg_); - bwp_slot_grid& operator[](tti_point tti) { return slots[tti.to_uint() % slots.capacity()]; }; - const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.to_uint() % slots.capacity()]; }; - uint32_t id() const { return bwp_id; } - uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; } - const sched_cell_params& cell_params() const { return *cell_cfg; } - const bwp_cfg_t& bwp_cfg() const { return cell_cfg->cell_cfg.bwps[id() - 1]; } + bwp_slot_grid& operator[](tti_point tti) { return slots[tti.to_uint() % slots.capacity()]; }; + const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.to_uint() % slots.capacity()]; }; + uint32_t id() const { return cfg->bwp_id; } + uint32_t nof_prbs() const { return cfg->cfg.rb_width; } - const sched_cell_params* cell_cfg = nullptr; + const bwp_params* cfg = nullptr; private: - uint32_t bwp_id; - srsran::bounded_vector slots; }; @@ -78,7 +75,7 @@ public: tti_point get_pdcch_tti() const { return pdcch_tti; } const bwp_res_grid& res_grid() const { return bwp_grid; } - const sched_cell_params& cfg; + const bwp_params& cfg; private: srslog::basic_logger& logger; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 86c2af5ed..f2a44580d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -33,7 +33,7 @@ using ul_sched_t = sched_nr_interface::ul_sched_t; class slot_cc_worker { public: - explicit slot_cc_worker(cell_sched& sched); + explicit slot_cc_worker(serv_cell_ctxt& sched); void start(tti_point tti_rx_, ue_map_t& ue_db_); void run(); @@ -45,7 +45,7 @@ private: void alloc_ul_ues(); const sched_cell_params& cfg; - cell_sched& cell; + serv_cell_ctxt& cell; tti_point tti_rx; bwp_slot_allocator bwp_alloc; @@ -82,7 +82,7 @@ private: std::vector > slot_worker_ctxts; - srsran::bounded_vector cell_grid_list; + srsran::bounded_vector cell_grid_list; slot_worker_ctxt& get_sf(tti_point tti_rx); }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc index ac59dcbd9..27886cb28 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -17,8 +17,7 @@ namespace srsenb { namespace sched_nr_impl { -ra_sched::ra_sched(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_), logger(srslog::fetch_basic_logger("MAC")) -{} +ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {} alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) @@ -29,7 +28,7 @@ ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_ alloc_result ret = alloc_result::other_cause; for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { ret = alloc_result::invalid_coderate; - for (uint32_t nrbg = 1; nrbg < cell_cfg->cell_cfg.nof_rbg and ret == alloc_result::invalid_coderate; ++nrbg) { + for (uint32_t nrbg = 1; nrbg < bwp_cfg->N_rbg and ret == alloc_result::invalid_coderate; ++nrbg) { rbg_interval rbg_interv = find_empty_rbg_interval(pdsch_bitmap, nrbg); if (rbg_interv.length() == nrbg) { ret = slot_grid.alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc); @@ -61,7 +60,7 @@ void ra_sched::run_slot(bwp_slot_allocator& slot_grid) // - if window has passed, discard RAR // - if window hasn't started, stop loop, as RARs are ordered by TTI tti_interval rar_window{rar.prach_tti + PRACH_RAR_OFFSET, - rar.prach_tti + PRACH_RAR_OFFSET + cell_cfg->cell_cfg.rar_window_size}; + rar.prach_tti + PRACH_RAR_OFFSET + bwp_cfg->cfg.rar_window_size}; if (not rar_window.contains(pdcch_tti)) { if (pdcch_tti >= rar_window.stop()) { fmt::memory_buffer str_buffer; @@ -142,14 +141,12 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) return SRSRAN_SUCCESS; } -bwp_sched::bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : - cell_cfg(&cell_cfg_), bwp_id(bwp_id_), ra(cell_cfg_), grid(cell_cfg_, bwp_id_) -{} +bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg) {} -cell_sched::cell_sched(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) +serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) { for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { - bwps.emplace_back(cell_cfg_, bwp_id); + bwps.emplace_back(cell_cfg_.bwps[bwp_id]); } } diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 99fe100ba..3d918af1a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -16,9 +16,23 @@ namespace srsenb { namespace sched_nr_impl { +bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc_, uint32_t bwp_id_) : + cell_cfg(cell), sched_cfg(sched_cfg_), cc(cc_), bwp_id(bwp_id_), cfg(cell.bwps[bwp_id_]) +{ + P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1); + N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1); + srsran_assert(cfg.coresets[0].has_value(), "At least one coreset has to be active per BWP"); +} + sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) -{} +{ + bwps.reserve(cell.bwps.size()); + for (uint32_t i = 0; i < cell.bwps.size(); ++i) { + bwps.emplace_back(cell, sched_cfg_, cc, i); + } + srsran_assert(not bwps.empty(), "No BWPs were configured"); +} sched_params::sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {} diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 526858bbd..ece19894e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -16,13 +16,13 @@ namespace srsenb { namespace sched_nr_impl { -coreset_region::coreset_region(const bwp_cfg_t& bwp_cfg_, - uint32_t coreset_id_, - uint32_t slot_idx_, - pdcch_dl_list_t& dl_list_, - pdcch_ul_list_t& ul_list_) : +coreset_region::coreset_region(const bwp_params& bwp_cfg_, + uint32_t coreset_id_, + uint32_t slot_idx_, + pdcch_dl_list_t& dl_list_, + pdcch_ul_list_t& ul_list_) : bwp_cfg(&bwp_cfg_), - coreset_cfg(&bwp_cfg_.coresets[coreset_id_ - 1].value()), + coreset_cfg(&bwp_cfg_.cfg.coresets[coreset_id_].value()), coreset_id(coreset_id_), slot_idx(slot_idx_), pdcch_dl_list(dl_list_), @@ -173,8 +173,8 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor switch (record.alloc_type) { case pdcch_grant_type_t::dl_data: return record.ue->cfg->cc_params[record.ue->cc] - .bwps[bwp_cfg->bwp_id - 1] - .coresets[coreset_id - 1] + .bwps[bwp_cfg->bwp_id] + .coresets[coreset_id] .cce_positions[slot_idx][record.aggr_idx]; default: break; diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy.cc b/srsenb/src/stack/mac/nr/sched_nr_phy.cc index e8403abe0..bd5a4c0c7 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy.cc @@ -17,7 +17,7 @@ namespace srsenb { namespace sched_nr_impl { -/// Table 6.1.2.2.1-1 - Nominal RBG size P +/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2) { srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size"); @@ -33,6 +33,7 @@ uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2) return 16; } +/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2) { uint32_t P = get_P(bwp_nof_prb, config1_or_2); @@ -108,20 +109,20 @@ rbg_interval find_empty_rbg_interval(const pdsch_bitmap& in_mask, uint32_t max_s //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci) +bool fill_dci_rar(rbg_interval rbginterv, const bwp_params& cell, srsran_dci_dl_nr_t& dci) { dci.mcs = 5; return true; } template -void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci) +void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const bwp_params& bwp_cfg, DciDlOrUl& dci) { const static uint32_t rv_idx[4] = {0, 2, 3, 1}; // Note: PDCCH DCI position already filled at this point dci.bwp_id = ue.bwp_id; dci.cc_id = ue.cc; - dci.freq_domain_assigment = bitmap_to_riv(bitmap, cc_cfg.cell_cfg.nof_prb); + dci.freq_domain_assigment = bitmap_to_riv(bitmap, bwp_cfg.cfg.rb_width); dci.ctx.rnti = ue.rnti; dci.ctx.rnti_type = srsran_rnti_type_c; dci.tpc = 1; @@ -133,47 +134,35 @@ void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cel dci.rv = rv_idx[h->nof_retx() % 4]; } -void fill_dci_ue_cfg(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_dci_dl_nr_t& dci) +void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci) { - fill_dci_common(ue, rbgmask, cc_cfg, dci); + fill_dci_common(ue, rbgmask, bwp_cfg, dci); } -void fill_dci_ue_cfg(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_dci_ul_nr_t& dci) +void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_ul_nr_t& dci) { - fill_dci_common(ue, rbgmask, cc_cfg, dci); + fill_dci_common(ue, rbgmask, bwp_cfg, dci); } -void fill_sch_ue_common(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch) +void fill_sch_ue_common(const slot_ue& ue, + const rbgmask_t& rbgmask, + const bwp_params& bwp_cfg, + srsran_sch_cfg_nr_t& sch) { sch.grant.rnti_type = srsran_rnti_type_c; sch.grant.rnti = ue.rnti; sch.grant.nof_layers = 1; - sch.grant.nof_prb = cc_cfg.cell_cfg.nof_prb; + sch.grant.nof_prb = bwp_cfg.cfg.rb_width; } -void fill_pdsch_ue(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch) +void fill_pdsch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& cc_cfg, srsran_sch_cfg_nr_t& sch) { fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); sch.grant.k = ue.cc_cfg->pdsch_res_list[0].k0; sch.grant.dci_format = srsran_dci_format_nr_1_0; } -void fill_pusch_ue(const slot_ue& ue, - const rbgmask_t& rbgmask, - const sched_cell_params& cc_cfg, - srsran_sch_cfg_nr_t& sch) +void fill_pusch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& cc_cfg, srsran_sch_cfg_nr_t& sch) { fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); sch.grant.k = ue.cc_cfg->pusch_res_list[0].k2; diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 57a0a0caa..7a008f0a5 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -18,16 +18,16 @@ namespace sched_nr_impl { #define NUMEROLOGY_IDX 0 -bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) : - dl_rbgs(cell_params.cell_cfg.nof_rbg), - ul_rbgs(cell_params.cell_cfg.nof_rbg), - bwp_id(bwp_id_), +bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : + dl_rbgs(bwp_cfg_.N_rbg), + ul_rbgs(bwp_cfg_.N_rbg), slot_idx(slot_idx_), - is_dl(srsran_tdd_nr_is_dl(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)), - is_ul(srsran_tdd_nr_is_ul(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) + cfg(&bwp_cfg_), + is_dl(srsran_tdd_nr_is_dl(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)), + is_ul(srsran_tdd_nr_is_ul(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) { - const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported - coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, dl_pdcchs, ul_pdcchs); + const uint32_t coreset_id = 0; // Note: for now only one coreset per BWP supported + coresets.emplace_back(*cfg, coreset_id, slot_idx_, dl_pdcchs, ul_pdcchs); } void bwp_slot_grid::reset() @@ -42,17 +42,17 @@ void bwp_slot_grid::reset() pucchs.clear(); } -bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_), cell_cfg(&cell_cfg_) +bwp_res_grid::bwp_res_grid(const bwp_params& bwp_cfg_) : cfg(&bwp_cfg_) { for (uint32_t sl = 0; sl < slots.capacity(); ++sl) { - slots.emplace_back(cell_cfg_, bwp_id, sl % static_cast(SRSRAN_NSLOTS_PER_FRAME_NR(0u))); + slots.emplace_back(*cfg, sl % static_cast(SRSRAN_NSLOTS_PER_FRAME_NR(0u))); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : - logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cell_cfg), bwp_grid(bwp_grid_) + logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_) {} alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx, @@ -81,7 +81,7 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t // Check Msg3 RB collision uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants; - uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.bwp_cfg().rb_width, false)); + uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false)); rbg_interval msg3_rbgs = find_empty_rbg_interval(bwp_msg3_slot.ul_rbgs, total_ul_nof_rbgs); if (msg3_rbgs.length() < total_ul_nof_rbgs) { logger.debug("SCHED: No space in PUSCH for Msg3."); @@ -98,7 +98,7 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t // Generate DCI for RAR pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); - if (not fill_dci_rar(interv, bwp_grid.cell_params(), pdcch.dci)) { + if (not fill_dci_rar(interv, *bwp_grid.cfg, pdcch.dci)) { // Cancel on-going PDCCH allocation bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); return alloc_result::invalid_coderate; @@ -158,7 +158,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_ma // Allocation Successful pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); - fill_dci_ue_cfg(ue, dl_mask, bwp_grid.cell_params(), pdcch.dci); + fill_dci_ue_cfg(ue, dl_mask, *bwp_grid.cfg, pdcch.dci); pdsch_mask |= dl_mask; bwp_uci_slot.pucchs.emplace_back(); pucch_grant& pucch = bwp_uci_slot.pucchs.back(); @@ -209,7 +209,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_ma // Allocation Successful pdcch_ul_t& pdcch = pdcchs.back(); - fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdcch.dci); + fill_dci_ue_cfg(ue, ul_mask, *bwp_grid.cfg, pdcch.dci); pusch_mask |= ul_mask; return alloc_result::success; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 2895ada6b..a5310ea72 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -15,7 +15,7 @@ namespace srsenb { namespace sched_nr_impl { -slot_cc_worker::slot_cc_worker(cell_sched& cc_sched) : +slot_cc_worker::slot_cc_worker(serv_cell_ctxt& cc_sched) : cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid) {} @@ -79,7 +79,7 @@ void slot_cc_worker::alloc_dl_ues() return; } - rbgmask_t dlmask(cfg.cell_cfg.nof_rbg); + rbgmask_t dlmask(cfg.bwps[0].N_rbg); dlmask.fill(0, dlmask.size(), true); bwp_alloc.alloc_pdsch(ue, dlmask); } @@ -94,7 +94,7 @@ void slot_cc_worker::alloc_ul_ues() return; } - rbgmask_t ulmask(cfg.cell_cfg.nof_rbg); + rbgmask_t ulmask(cfg.bwps[0].N_rbg); ulmask.fill(0, ulmask.size(), true); bwp_alloc.alloc_pusch(ue, ulmask); } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 60f1924c1..fd62e0b1e 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -44,10 +44,8 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() // Disable pattern 2 cell_cfg.tdd.pattern2.period_ms = 0; - cell_cfg.bwps.resize(2); + cell_cfg.bwps.resize(1); cell_cfg.bwps[0].coresets[0].emplace(get_default_coreset()); - cell_cfg.bwps[0].coresets[1].emplace(get_default_coreset()); - cell_cfg.bwps[0].coresets[1].value().id = 1; return cell_cfg; } std::vector get_default_cells_cfg(uint32_t nof_sectors) From b81cbd1334d73d3cf969a7e58851220c6e3521c5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 8 Jul 2021 12:19:09 +0100 Subject: [PATCH 53/59] sched,nr: redesign the order available search spaces/coresets are found in the scheduler --- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 45 ++++++++++++++---- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 3 +- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 3 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 12 ++--- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 42 +++++++++++++---- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 21 +++++---- srsenb/src/stack/mac/nr/sched_nr_phy.cc | 4 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 36 +++++++++------ srsenb/src/stack/mac/nr/sched_nr_ue.cc | 12 +++-- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 11 ++--- srsenb/test/mac/nr/sched_nr_test.cc | 48 ++++++++++++-------- 12 files changed, 154 insertions(+), 85 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 0e78bae23..bf304407a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -83,30 +83,57 @@ void get_dci_locs(const srsran_coreset_t& coreset, using ue_cfg_t = sched_nr_interface::ue_cfg_t; using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; +class bwp_ue_cfg +{ +public: + bwp_ue_cfg() = default; + explicit bwp_ue_cfg(uint16_t rnti, const bwp_params& bwp_cfg, const ue_cfg_t& uecfg_); + + const ue_cfg_t* ue_cfg() const { return cfg_; } + const srsran::phy_cfg_nr_t& cfg() const { return cfg_->phy_cfg; } + const bwp_cce_pos_list& cce_pos_list(uint32_t search_id) const + { + return cce_positions_list[ss_id_to_cce_idx[search_id]]; + } + +private: + uint16_t rnti = SRSRAN_INVALID_RNTI; + const bwp_params* bwp_cfg = nullptr; + const ue_cfg_t* cfg_ = nullptr; + + std::vector cce_positions_list; + std::array ss_id_to_cce_idx; +}; + class ue_cfg_extended : public ue_cfg_t { public: struct search_space_params { - srsran_search_space_t* cfg = nullptr; + const srsran_search_space_t* cfg; + bwp_cce_pos_list cce_positions; }; struct coreset_params { - srsran_coreset_t* cfg = nullptr; - std::vector ss_list; - bwp_cce_pos_list cce_positions; + srsran_coreset_t* cfg = nullptr; + std::vector ss_list; }; struct bwp_params { - std::vector search_spaces; - std::vector coresets; + std::array, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE> ss_list; + std::vector coresets; }; struct cc_params { srsran::bounded_vector bwps; }; - uint16_t rnti; - std::vector cc_params; - ue_cfg_extended() = default; explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); + + const bwp_cce_pos_list& get_dci_pos_list(uint32_t cc, uint32_t bwp_id, uint32_t search_space_id) const + { + return cc_params[cc].bwps[bwp_id].ss_list[search_space_id]->cce_positions; + } + + uint16_t rnti; + std::vector cc_params; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 164b837f9..91b1e4cc5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -51,11 +51,10 @@ public: struct bwp_cfg_t { uint32_t start_rb = 0; uint32_t rb_width = 100; + srsran_pdcch_cfg_nr_t pdcch = {}; srsran_sch_hl_cfg_nr_t pdsch = {}; srsran_sch_hl_cfg_nr_t pusch = {}; uint32_t rar_window_size = 3; - - std::array, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets; }; struct cell_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index 60d4c2772..fc1f757ff 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -52,7 +52,7 @@ public: * @param user UE object or null in case of broadcast/RAR/paging allocation * @return if the allocation was successful */ - bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, slot_ue* user = nullptr); + bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t search_space_id, slot_ue* user = nullptr); void rem_last_dci(); @@ -71,6 +71,7 @@ private: // List of PDCCH grants struct alloc_record { uint32_t aggr_idx; + uint32_t search_space_id; uint32_t idx; pdcch_grant_type_t alloc_type; slot_ue* ue; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 0a8dbf98f..d2c221dbd 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -28,7 +28,7 @@ struct pending_rar_t; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const static size_t MAX_CORESET_PER_BWP = 3; -using slot_coreset_list = srsran::bounded_vector; +using slot_coreset_list = std::array, MAX_CORESET_PER_BWP>; struct bwp_slot_grid { uint32_t slot_idx; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index d56f11a43..fa95640fc 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -41,8 +41,8 @@ public: uint32_t cc = SCHED_NR_MAX_CARRIERS; // UE parameters common to all sectors - const ue_cfg_extended* cfg = nullptr; - bool pending_sr; + const bwp_ue_cfg* cfg = nullptr; + bool pending_sr; // UE parameters that are sector specific const ue_cc_cfg_t* cc_cfg = nullptr; @@ -64,7 +64,7 @@ class ue_carrier { public: ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_); - slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_extended& cfg); + slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_t& cfg); void push_feedback(srsran::move_callback callback); const uint16_t rnti; @@ -77,7 +77,7 @@ public: harq_entity harq_ent; private: - const ue_cfg_t* cfg = nullptr; + bwp_ue_cfg bwp_cfg; const sched_cell_params& cell_params; resource_guard busy; @@ -105,8 +105,8 @@ private: bool pending_sr = false; - int current_idx = 0; - std::array ue_cfgs; + int current_idx = 0; + std::array ue_cfgs; }; using ue_map_t = srsran::static_circular_map, SCHED_NR_MAX_USERS>; diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 3d918af1a..a0103118e 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -21,7 +21,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui { P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1); N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1); - srsran_assert(cfg.coresets[0].has_value(), "At least one coreset has to be active per BWP"); + + srsran_assert(bwp_id != 0 or cfg.pdcch.coreset_present[0], "CORESET#0 has to be active for initial BWP"); } sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) : @@ -56,6 +57,26 @@ void get_dci_locs(const srsran_coreset_t& coreset, /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bwp_ue_cfg::bwp_ue_cfg(uint16_t rnti_, const bwp_params& bwp_cfg_, const ue_cfg_t& uecfg_) : + rnti(rnti_), cfg_(&uecfg_), bwp_cfg(&bwp_cfg_) +{ + std::fill(ss_id_to_cce_idx.begin(), ss_id_to_cce_idx.end(), SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); + const auto& pdcch = cfg().pdcch; + for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++i) { + if (pdcch.search_space_present[i]) { + const auto& ss = pdcch.search_space[i]; + srsran_assert(pdcch.coreset_present[ss.coreset_id], + "Invalid mapping search space id=%d to coreset id=%d", + ss.id, + ss.coreset_id); + const auto& coreset = pdcch.coreset[ss.coreset_id]; + cce_positions_list.emplace_back(); + get_dci_locs(coreset, ss, rnti, cce_positions_list.back()); + ss_id_to_cce_idx[ss.id] = cce_positions_list.size() - 1; + } + } +} + ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_) { cc_params.resize(carriers.size()); @@ -64,19 +85,20 @@ ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg auto& bwp = cc_params[cc].bwps[0]; for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) { if (phy_cfg.pdcch.search_space_present[ssid]) { - bwp.search_spaces.emplace_back(); - bwp.search_spaces.back().cfg = &phy_cfg.pdcch.search_space[ssid]; + auto& ss = phy_cfg.pdcch.search_space[ssid]; + bwp.ss_list[ss.id].emplace(); + bwp.ss_list[ss.id]->cfg = &ss; + get_dci_locs(phy_cfg.pdcch.coreset[ss.coreset_id], ss, rnti, bwp.ss_list[ss.id]->cce_positions); } } - for (uint32_t csid = 0; csid < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++csid) { - if (phy_cfg.pdcch.coreset_present[csid]) { + for (uint32_t idx = 0; idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++idx) { + if (phy_cfg.pdcch.coreset_present[idx]) { bwp.coresets.emplace_back(); auto& coreset = bwp.coresets.back(); - coreset.cfg = &phy_cfg.pdcch.coreset[csid]; - for (auto& ss : bwp.search_spaces) { - if (ss.cfg->coreset_id == csid + 1) { - coreset.ss_list.push_back(&ss); - get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions); + coreset.cfg = &phy_cfg.pdcch.coreset[idx]; + for (auto& ss : bwp.ss_list) { + if (ss.has_value() and ss->cfg->coreset_id == coreset.cfg->id) { + coreset.ss_list.push_back(ss->cfg->id); } } } diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index ece19894e..023a81eef 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -22,7 +22,7 @@ coreset_region::coreset_region(const bwp_params& bwp_cfg_, pdcch_dl_list_t& dl_list_, pdcch_ul_list_t& ul_list_) : bwp_cfg(&bwp_cfg_), - coreset_cfg(&bwp_cfg_.cfg.coresets[coreset_id_].value()), + coreset_cfg(&bwp_cfg_.cfg.pdcch.coreset[coreset_id_]), coreset_id(coreset_id_), slot_idx(slot_idx_), pdcch_dl_list(dl_list_), @@ -43,7 +43,10 @@ void coreset_region::reset() pdcch_ul_list.clear(); } -bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, slot_ue* user) +bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, + uint32_t aggr_idx, + uint32_t search_space_id, + slot_ue* user) { srsran_assert(aggr_idx <= 4, "Invalid DCI aggregation level=%d", 1U << aggr_idx); srsran_assert((user == nullptr) xor @@ -52,9 +55,10 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, saved_dfs_tree.clear(); alloc_record record; - record.ue = user; - record.aggr_idx = aggr_idx; - record.alloc_type = alloc_type; + record.ue = user; + record.aggr_idx = aggr_idx; + record.search_space_id = search_space_id; + record.alloc_type = alloc_type; if (record.alloc_type == pdcch_grant_type_t::ul_data) { record.idx = pdcch_ul_list.size(); pdcch_ul_list.emplace_back(); @@ -172,10 +176,9 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor { switch (record.alloc_type) { case pdcch_grant_type_t::dl_data: - return record.ue->cfg->cc_params[record.ue->cc] - .bwps[bwp_cfg->bwp_id] - .coresets[coreset_id] - .cce_positions[slot_idx][record.aggr_idx]; + return record.ue->cfg->cce_pos_list(record.search_space_id)[slot_idx][record.aggr_idx]; + case pdcch_grant_type_t::ul_data: + return record.ue->cfg->cce_pos_list(record.search_space_id)[slot_idx][record.aggr_idx]; default: break; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy.cc b/srsenb/src/stack/mac/nr/sched_nr_phy.cc index bd5a4c0c7..4652db3a1 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy.cc @@ -171,9 +171,9 @@ void fill_pusch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs) { - if (ue.cfg->phy_cfg.pucch.enabled) { + if (ue.cfg->cfg().pucch.enabled) { for (uint32_t i = 0; i < SRSRAN_PUCCH_NR_MAX_NOF_SETS; ++i) { - const auto& rset = ue.cfg->phy_cfg.pucch.sets[i]; + const auto& rset = ue.cfg->cfg().pucch.sets[i]; if (rset.max_payload_size >= tbs) { for (uint32_t sid = 0; sid < rset.nof_resources; ++sid) { return pucch_resource_grant{ue.rnti, i, sid}; diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 7a008f0a5..efb271b0b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -26,14 +26,20 @@ bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : is_dl(srsran_tdd_nr_is_dl(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)), is_ul(srsran_tdd_nr_is_ul(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)) { - const uint32_t coreset_id = 0; // Note: for now only one coreset per BWP supported - coresets.emplace_back(*cfg, coreset_id, slot_idx_, dl_pdcchs, ul_pdcchs); + for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) { + if (cfg->cfg.pdcch.coreset_present[cs_idx]) { + uint32_t cs_id = cfg->cfg.pdcch.coreset[cs_idx].id; + coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl_pdcchs, ul_pdcchs); + } + } } void bwp_slot_grid::reset() { for (auto& coreset : coresets) { - coreset.reset(); + if (coreset.has_value()) { + coreset->reset(); + } } dl_rbgs.reset(); ul_rbgs.reset(); @@ -89,8 +95,9 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t } // Find PDCCH position - const uint32_t coreset_id = 0; - if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::rar, aggr_idx, nullptr)) { + const uint32_t coreset_id = cfg.cfg.pdcch.ra_search_space.coreset_id; + const uint32_t search_space_id = cfg.cfg.pdcch.ra_search_space.id; + if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::rar, aggr_idx, search_space_id, nullptr)) { // Could not find space in PDCCH logger.debug("SCHED: No space in PDCCH for DL tx."); return alloc_result::no_cch_space; @@ -100,7 +107,7 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); if (not fill_dci_rar(interv, *bwp_grid.cfg, pdcch.dci)) { // Cancel on-going PDCCH allocation - bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); + bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); return alloc_result::invalid_coderate; } @@ -132,8 +139,9 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_ma if ((pdsch_mask & dl_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, coreset_id = 0; - if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, &ue)) { + const uint32_t aggr_idx = 2, search_space_id = 1; + uint32_t coreset_id = ue.cfg->cfg().pdcch.search_space[search_space_id].coreset_id; + if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, search_space_id, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -152,7 +160,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_ma pucch_resource_grant pucch_res = find_pucch_resource(ue, bwp_uci_slot.ul_rbgs, tbs); if (pucch_res.rnti != SRSRAN_INVALID_RNTI) { // Could not find space in PUCCH for HARQ-ACK - bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); + bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); return alloc_result::no_cch_space; } @@ -164,7 +172,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_ma pucch_grant& pucch = bwp_uci_slot.pucchs.back(); pucch.resource = pucch_res; bwp_uci_slot.ul_rbgs.set( - ue.cfg->phy_cfg.pucch.sets[pucch_res.resource_set_id].resources[pucch_res.resource_id].starting_prb); + ue.cfg->cfg().pucch.sets[pucch_res.resource_set_id].resources[pucch_res.resource_id].starting_prb); return alloc_result::success; } @@ -190,8 +198,10 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_ma if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, coreset_id = 0; - if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, &ue)) { + const uint32_t aggr_idx = 2, search_space_id = 1; + uint32_t coreset_id = ue.cfg->cfg().pdcch.search_space[search_space_id].coreset_id; + if (not bwp_pdcch_slot.coresets[coreset_id].value().alloc_dci( + pdcch_grant_type_t::ul_data, aggr_idx, search_space_id, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } @@ -200,7 +210,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_ma if (ue.h_ul->empty()) { mcs = 20; tbs = 100; - bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->maxharq_tx); + bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); srsran_assert(ret, "Failed to allocate UL HARQ"); } else { srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask, &mcs, &tbs), diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 1d22f5389..59b5f979a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -23,7 +23,7 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) : - rnti(rnti_), cc(cell_params_.cc), cfg(&uecfg_), cell_params(cell_params_) + rnti(rnti_), cc(cell_params_.cc), bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_), cell_params(cell_params_) {} void ue_carrier::push_feedback(srsran::move_callback callback) @@ -31,14 +31,16 @@ void ue_carrier::push_feedback(srsran::move_callback callback pending_feedback.push_back(std::move(callback)); } -slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) +slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) { slot_ue sfu(busy, rnti, tti_rx, cc); if (sfu.empty()) { return sfu; } // successfully acquired. Process any CC-specific pending feedback - cfg = &uecfg_; + if (bwp_cfg.ue_cfg() != &uecfg_) { + bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], uecfg_); + } while (not pending_feedback.empty()) { pending_feedback.front()(*this); pending_feedback.pop_front(); @@ -53,7 +55,7 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) } // set UE parameters common to all carriers - sfu.cfg = &uecfg_; + sfu.cfg = &bwp_cfg; // copy cc-specific parameters and find available HARQs sfu.cc_cfg = &uecfg_.carriers[cc]; @@ -92,7 +94,7 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_) ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rnti(rnti_), sched_cfg(sched_cfg_) { - ue_cfgs[0] = ue_cfg_extended(rnti, cfg); + ue_cfgs[0] = cfg; for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) { if (cfg.carriers[cc].active) { carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc])); diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index a5310ea72..e18807a6f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -49,14 +49,9 @@ void slot_cc_worker::run() // Allocate pending RARs cell.bwps[0].ra.run_slot(bwp_alloc); - // Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion - if ((tti_rx.to_uint() & 0x1u) == 0) { - alloc_dl_ues(); - alloc_ul_ues(); - } else { - alloc_ul_ues(); - alloc_dl_ues(); - } + // TODO: Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion + alloc_dl_ues(); + alloc_ul_ues(); } void slot_cc_worker::end_tti() diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index fd62e0b1e..e6977674c 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -12,6 +12,7 @@ #include "sched_nr_sim_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/test_common.h" #include "srsran/common/thread_pool.h" @@ -19,7 +20,10 @@ namespace srsenb { using dl_sched_t = sched_nr_interface::dl_sched_t; -srsran_coreset_t get_default_coreset() +static const srsran::phy_cfg_nr_t default_phy_cfg = + srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}; + +srsran_coreset_t get_default_coreset0() { srsran_coreset_t coreset{}; coreset.id = 0; @@ -45,7 +49,29 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() cell_cfg.tdd.pattern2.period_ms = 0; cell_cfg.bwps.resize(1); - cell_cfg.bwps[0].coresets[0].emplace(get_default_coreset()); + cell_cfg.bwps[0].pdcch.coreset_present[0] = true; + cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); + cell_cfg.bwps[0].pdcch.coreset_present[1] = true; + cell_cfg.bwps[0].pdcch.coreset[1] = default_phy_cfg.pdcch.coreset[1]; + + cell_cfg.bwps[0].pdcch.search_space_present[0] = true; + auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; + ss.id = 0; + ss.coreset_id = 0; + ss.duration = 1; + ss.type = srsran_search_space_type_common_0; + ss.nof_candidates[0] = 1; + ss.nof_candidates[1] = 1; + ss.nof_candidates[2] = 1; + ss.nof_candidates[3] = 0; + ss.nof_candidates[4] = 0; + ss.nof_formats = 1; + ss.formats[0] = srsran_dci_format_nr_1_0; + cell_cfg.bwps[0].pdcch.search_space_present[1] = true; + cell_cfg.bwps[0].pdcch.search_space[1] = default_phy_cfg.pdcch.search_space[1]; + cell_cfg.bwps[0].pdcch.ra_search_space_present = true; + cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; + return cell_cfg; } std::vector get_default_cells_cfg(uint32_t nof_sectors) @@ -65,23 +91,7 @@ sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) for (uint32_t cc = 0; cc < nof_cc; ++cc) { uecfg.carriers[cc].active = true; } - uecfg.phy_cfg.pdcch.coreset_present[0] = true; - uecfg.phy_cfg.pdcch.coreset[0] = get_default_coreset(); - uecfg.phy_cfg.pdcch.coreset[0].id = 1; - - uecfg.phy_cfg.pdcch.search_space_present[0] = true; - auto& ss = uecfg.phy_cfg.pdcch.search_space[0]; - ss.id = 1; - ss.coreset_id = 1; - ss.duration = 1; - ss.type = srsran_search_space_type_common_0; - ss.nof_candidates[0] = 1; - ss.nof_candidates[1] = 1; - ss.nof_candidates[2] = 1; - ss.nof_candidates[3] = 0; - ss.nof_candidates[4] = 0; - ss.nof_formats = 1; - ss.formats[0] = srsran_dci_format_nr_1_0; + uecfg.phy_cfg = default_phy_cfg; return uecfg; } From d63ea00a5d938234875bac0293c64ac379e234e3 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 9 Jul 2021 18:37:29 +0100 Subject: [PATCH 54/59] sched,nr: use PRBs instead of RBGs as the basic unit for PRB grants in the NR scheduler --- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 14 +- srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 22 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 12 +- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 2 +- srsenb/hdr/stack/mac/nr/sched_nr_phy.h | 29 ++- srsenb/hdr/stack/mac/nr/sched_nr_rb.h | 238 +++++++++++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 13 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/sched_nr_bwp.cc | 16 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_harq.cc | 38 ++- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 13 +- srsenb/src/stack/mac/nr/sched_nr_phy.cc | 193 ++++----------- srsenb/src/stack/mac/nr/sched_nr_rb.cc | 106 +++++++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 107 +++++---- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 9 +- srsenb/test/mac/nr/CMakeLists.txt | 8 + srsenb/test/mac/nr/sched_nr_prb_test.cc | 130 ++++++++++ srsenb/test/mac/nr/sched_nr_test.cc | 10 +- 19 files changed, 686 insertions(+), 278 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/sched_nr_rb.h create mode 100644 srsenb/src/stack/mac/nr/sched_nr_rb.cc create mode 100644 srsenb/test/mac/nr/sched_nr_prb_test.cc diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index bf304407a..1f3b7097a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -14,7 +14,7 @@ #define SRSRAN_SCHED_NR_CFG_H #include "sched_nr_interface.h" -#include "srsran/adt/bounded_bitset.h" +#include "sched_nr_rb.h" namespace srsenb { @@ -27,9 +27,10 @@ namespace sched_nr_impl { const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS; -using pucch_resource_grant = sched_nr_interface::pucch_resource_grant; -using pucch_grant = sched_nr_interface::pucch_grant; -using pucch_list_t = sched_nr_interface::pucch_list_t; +using pucch_t = mac_interface_phy_nr::pucch_t; +using pucch_list_t = srsran::bounded_vector; +using pusch_t = mac_interface_phy_nr::pusch_t; +using pusch_list_t = srsran::bounded_vector; using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; @@ -67,7 +68,8 @@ struct sched_params { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -using rbgmask_t = srsran::bounded_bitset; +using prb_bitmap = srsran::bounded_bitset; +using rbgmask_t = srsran::bounded_bitset; using pdcchmask_t = srsran::bounded_bitset; @@ -90,7 +92,7 @@ public: explicit bwp_ue_cfg(uint16_t rnti, const bwp_params& bwp_cfg, const ue_cfg_t& uecfg_); const ue_cfg_t* ue_cfg() const { return cfg_; } - const srsran::phy_cfg_nr_t& cfg() const { return cfg_->phy_cfg; } + const srsran::phy_cfg_nr_t& phy() const { return cfg_->phy_cfg; } const bwp_cce_pos_list& cce_pos_list(uint32_t search_id) const { return cce_positions_list[ss_id_to_cce_idx[search_id]]; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 1d5286a88..90644e602 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -31,19 +31,25 @@ public: } bool empty(uint32_t tb_idx) const { return not tb[tb_idx].active; } bool has_pending_retx(tti_point tti_rx) const { return not empty() and not tb[0].ack_state and tti_ack <= tti_rx; } - uint32_t nof_retx() const { return tb[0].n_rtx; } - uint32_t max_nof_retx() const { return max_retx; } - uint32_t tbs() const { return tb[0].tbs; } - uint32_t ndi() const { return tb[0].ndi; } - uint32_t mcs() const { return tb[0].mcs; } + uint32_t nof_retx() const { return tb[0].n_rtx; } + uint32_t max_nof_retx() const { return max_retx; } + uint32_t tbs() const { return tb[0].tbs; } + uint32_t ndi() const { return tb[0].ndi; } + uint32_t mcs() const { return tb[0].mcs; } + const prb_grant& prbs() const { return prbs_; } + tti_point harq_tti_ack() const { return tti_ack; } bool ack_info(uint32_t tb_idx, bool ack); void new_tti(tti_point tti_rx); void reset(); bool - new_tx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t tbs, uint32_t max_retx); - bool new_retx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, int* mcs, int* tbs); + new_tx(tti_point tti_tx, tti_point tti_ack, const prb_grant& grant, uint32_t mcs, uint32_t tbs, uint32_t max_retx); + bool new_retx(tti_point tti_tx, tti_point tti_ack, const prb_grant& grant); + bool new_retx(tti_point tti_tx, tti_point tti_ack); + + // NOTE: Has to be used before first tx is dispatched + bool set_tbs(uint32_t tbs); const uint32_t pid; @@ -60,7 +66,7 @@ private: uint32_t max_retx = 1; tti_point tti_tx; tti_point tti_ack; - rbgmask_t rbgmask; + prb_grant prbs_; std::array tb; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 91b1e4cc5..23b1093cb 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -26,7 +26,7 @@ namespace srsenb { const static size_t SCHED_NR_MAX_CARRIERS = 4; const static uint16_t SCHED_NR_INVALID_RNTI = 0; -const static size_t SCHED_NR_MAX_NOF_RBGS = 17; +const static size_t SCHED_NR_MAX_NOF_RBGS = 18; const static size_t SCHED_NR_MAX_TB = 1; const static size_t SCHED_NR_MAX_HARQ = 16; const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; @@ -93,16 +93,6 @@ public: using dl_sched_t = mac_interface_phy_nr::dl_sched_t; using ul_sched_t = mac_interface_phy_nr::ul_sched_t; - struct pucch_resource_grant { - uint16_t rnti; - uint32_t resource_set_id; - uint32_t resource_id; - }; - struct pucch_grant { - pucch_resource_grant resource; - }; - using pucch_list_t = srsran::bounded_vector; - virtual ~sched_nr_interface() = default; virtual int cell_cfg(srsran::const_span ue_cfg) = 0; virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index fc1f757ff..a846feef7 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -71,7 +71,7 @@ private: // List of PDCCH grants struct alloc_record { uint32_t aggr_idx; - uint32_t search_space_id; + uint32_t ss_id; uint32_t idx; pdcch_grant_type_t alloc_type; slot_ue* ue; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h index 549310e19..76141c847 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h @@ -18,26 +18,25 @@ namespace srsenb { namespace sched_nr_impl { -uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); -uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); - -using pdsch_bitmap = srsran::bounded_bitset; -using pusch_bitmap = srsran::bounded_bitset; -using rbg_interval = srsran::interval; - -rbg_interval find_empty_rbg_interval(const pdsch_bitmap& bitmap, uint32_t max_nof_rbgs); - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_rar(rbg_interval rbginterv, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci); +bool fill_dci_rar(prb_interval interv, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci); class slot_ue; -void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci); -void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_ul_nr_t& dci); -void fill_pdsch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_sch_cfg_nr_t& sch); -void fill_pusch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_sch_cfg_nr_t& sch); -pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs); +/// Generate PDCCH DL DCI fields +void fill_dl_dci_ue_fields(const slot_ue& ue, + const bwp_params& bwp_cfg, + uint32_t ss_id, + srsran_dci_location_t dci_pos, + srsran_dci_dl_nr_t& dci); + +/// Generate PDCCH UL DCI fields +void fill_ul_dci_ue_fields(const slot_ue& ue, + const bwp_params& bwp_cfg, + uint32_t ss_id, + srsran_dci_location_t dci_pos, + srsran_dci_ul_nr_t& dci); } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h new file mode 100644 index 000000000..9fda7eacd --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h @@ -0,0 +1,238 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_RB_H +#define SRSRAN_SCHED_NR_RB_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsran/adt/bounded_bitset.h" +#include "srsran/phy/common/phy_common_nr.h" + +namespace srsenb { +namespace sched_nr_impl { + +using prb_bitmap = srsran::bounded_bitset; +using rbg_bitmap = srsran::bounded_bitset; + +/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P +uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); + +/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs +uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); + +/// Struct to express a {min,...,max} range of PRBs +struct prb_interval : public srsran::interval { + using interval::interval; +}; + +struct prb_grant { + prb_grant() = default; + prb_grant(const prb_interval& other) noexcept : alloc_type_0(false), alloc(other) {} + prb_grant(const rbg_bitmap& other) noexcept : alloc_type_0(true), alloc(other) {} + prb_grant(const prb_grant& other) noexcept : alloc_type_0(other.alloc_type_0), alloc(other.alloc_type_0, other.alloc) + {} + prb_grant& operator=(const prb_grant& other) noexcept + { + if (this == &other) { + return *this; + } + if (other.alloc_type_0) { + *this = other.rbgs(); + } else { + *this = other.prbs(); + } + return *this; + } + prb_grant& operator=(const prb_interval& prbs) + { + if (alloc_type_0) { + alloc_type_0 = false; + alloc.rbgs.~rbg_bitmap(); + new (&alloc.interv) prb_interval(prbs); + } else { + alloc.interv = alloc.interv; + } + return *this; + } + prb_grant& operator=(const rbg_bitmap& rbgs) + { + if (alloc_type_0) { + alloc.rbgs = rbgs; + } else { + alloc_type_0 = true; + alloc.interv.~prb_interval(); + new (&alloc.rbgs) rbg_bitmap(rbgs); + } + return *this; + } + ~prb_grant() + { + if (is_alloc_type0()) { + alloc.rbgs.~rbg_bitmap(); + } else { + alloc.interv.~prb_interval(); + } + } + + bool is_alloc_type0() const { return alloc_type_0; } + bool is_alloc_type1() const { return not is_alloc_type0(); } + const rbg_bitmap& rbgs() const + { + srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1"); + return alloc.rbgs; + } + const prb_interval& prbs() const + { + srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0"); + return alloc.interv; + } + rbg_bitmap& rbgs() + { + srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1"); + return alloc.rbgs; + } + prb_interval& prbs() + { + srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0"); + return alloc.interv; + } + +private: + bool alloc_type_0 = false; + union alloc_t { + rbg_bitmap rbgs; + prb_interval interv; + + alloc_t() : interv(0, 0) {} + explicit alloc_t(const prb_interval& prbs) : interv(prbs) {} + explicit alloc_t(const rbg_bitmap& rbgs_) : rbgs(rbgs_) {} + alloc_t(bool type0, const alloc_t& other) + { + if (type0) { + new (&rbgs) rbg_bitmap(other.rbgs); + } else { + new (&interv) prb_interval(other.interv); + } + } + } alloc; +}; + +struct bwp_rb_bitmap { +public: + bwp_rb_bitmap() = default; + bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2); + + void reset() + { + prbs_.reset(); + rbgs_.reset(); + } + + template + void operator|=(const T& grant) + { + add(grant); + } + + void add(const prb_interval& prbs) + { + prbs_.fill(prbs.start(), prbs.stop()); + add_prbs_to_rbgs(prbs); + } + void add(const prb_bitmap& grant) + { + prbs_ |= grant; + add_prbs_to_rbgs(grant); + } + void add(const rbg_bitmap& grant) + { + rbgs_ |= grant; + add_rbgs_to_prbs(grant); + } + void add(const prb_grant& grant) + { + if (grant.is_alloc_type0()) { + add(grant.rbgs()); + } else { + add(grant.prbs()); + } + } + bool collides(const prb_grant& grant) const + { + if (grant.is_alloc_type0()) { + return (rbgs() & grant.rbgs()).any(); + } + return prbs().any(grant.prbs().start(), grant.prbs().stop()); + } + bool test(uint32_t prb_idx) { return prbs().test(prb_idx); } + void set(uint32_t prb_idx) + { + prbs_.set(prb_idx); + rbgs_.set(prb_to_rbg_idx(prb_idx)); + } + + const prb_bitmap& prbs() const { return prbs_; } + const rbg_bitmap& rbgs() const { return rbgs_; } + uint32_t P() const { return P_; } + uint32_t nof_prbs() const { return prbs_.size(); } + uint32_t nof_rbgs() const { return rbgs_.size(); } + + uint32_t prb_to_rbg_idx(uint32_t prb_idx) const; + +private: + prb_bitmap prbs_; + rbg_bitmap rbgs_; + uint32_t bwp_prb_start = 0; + uint32_t P_ = 0; + uint32_t Pnofbits = 0; + uint32_t first_rbg_size = 0; + + void add_prbs_to_rbgs(const prb_bitmap& grant); + void add_prbs_to_rbgs(const prb_interval& grant); + void add_rbgs_to_prbs(const rbg_bitmap& grant); +}; + +inline prb_interval +find_next_empty_interval(const prb_bitmap& mask, size_t start_prb_idx = 0, size_t last_prb_idx = SRSRAN_MAX_PRB_NR) +{ + int rb_start = mask.find_lowest(start_prb_idx, std::min(mask.size(), last_prb_idx), false); + if (rb_start != -1) { + int rb_end = mask.find_lowest(rb_start + 1, std::min(mask.size(), last_prb_idx), true); + return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)}; + } + return {}; +} + +inline prb_interval find_empty_interval_of_length(const prb_bitmap& mask, size_t nof_prbs, uint32_t start_prb_idx = 0) +{ + prb_interval max_interv; + do { + prb_interval interv = find_next_empty_interval(mask, start_prb_idx, mask.size()); + if (interv.empty()) { + break; + } + if (interv.length() >= nof_prbs) { + max_interv.set(interv.start(), interv.start() + nof_prbs); + break; + } + if (interv.length() > max_interv.length()) { + max_interv = interv; + } + start_prb_idx = interv.stop() + 1; + } while (start_prb_idx < mask.size()); + return max_interv; +} + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_RB_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index d2c221dbd..ddbaf82be 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -30,17 +30,22 @@ struct pending_rar_t; const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = std::array, MAX_CORESET_PER_BWP>; +using pdsch_t = mac_interface_phy_nr::pdsch_t; +using pdsch_list_t = srsran::bounded_vector; + struct bwp_slot_grid { uint32_t slot_idx; const bwp_params* cfg; bool is_dl, is_ul; - pdsch_bitmap dl_rbgs; - pusch_bitmap ul_rbgs; + bwp_rb_bitmap dl_prbs; + bwp_rb_bitmap ul_prbs; pdcch_dl_list_t dl_pdcchs; pdcch_ul_list_t ul_pdcchs; + pdsch_list_t pdschs; slot_coreset_list coresets; pucch_list_t pucchs; + pusch_list_t puschs; bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); @@ -68,8 +73,8 @@ public: void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; } - alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, rbg_interval interv, uint32_t max_nof_grants); - alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); + alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, prb_interval interv, uint32_t max_nof_grants); + alloc_result alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); tti_point get_pdcch_tti() const { return pdcch_tti; } diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index d91ec20ae..0c3a2b2d5 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -7,6 +7,6 @@ # set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc - sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc) + sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc sched_nr_rb.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc index 27886cb28..223d05294 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -22,16 +22,18 @@ ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srsl alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) { - const uint32_t rar_aggr_level = 2; - auto& pdsch_bitmap = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_rbgs; + const uint32_t rar_aggr_level = 2; + const prb_bitmap& prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_prbs.prbs(); alloc_result ret = alloc_result::other_cause; for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { - ret = alloc_result::invalid_coderate; - for (uint32_t nrbg = 1; nrbg < bwp_cfg->N_rbg and ret == alloc_result::invalid_coderate; ++nrbg) { - rbg_interval rbg_interv = find_empty_rbg_interval(pdsch_bitmap, nrbg); - if (rbg_interv.length() == nrbg) { - ret = slot_grid.alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc); + ret = alloc_result::invalid_coderate; + uint32_t start_prb_idx = 0; + for (uint32_t nprb = 1; nprb < bwp_cfg->N_rbg and ret == alloc_result::invalid_coderate; ++nprb) { + prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx); + start_prb_idx = interv.stop(); + if (interv.length() == nprb) { + ret = slot_grid.alloc_rar(rar_aggr_level, rar, interv, nof_grants_alloc); } else { ret = alloc_result::no_sch_space; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index a0103118e..25e4f217a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -61,7 +61,7 @@ bwp_ue_cfg::bwp_ue_cfg(uint16_t rnti_, const bwp_params& bwp_cfg_, const ue_cfg_ rnti(rnti_), cfg_(&uecfg_), bwp_cfg(&bwp_cfg_) { std::fill(ss_id_to_cce_idx.begin(), ss_id_to_cce_idx.end(), SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE); - const auto& pdcch = cfg().pdcch; + const auto& pdcch = phy().pdcch; for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++i) { if (pdcch.search_space_present[i]) { const auto& ss = pdcch.search_space[i]; diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsenb/src/stack/mac/nr/sched_nr_harq.cc index db4cab24a..4bc674d07 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_harq.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_harq.cc @@ -45,7 +45,7 @@ void harq_proc::reset() bool harq_proc::new_tx(tti_point tti_tx_, tti_point tti_ack_, - const rbgmask_t& rbgmask_, + const prb_grant& grant, uint32_t mcs, uint32_t tbs, uint32_t max_retx_) @@ -57,7 +57,7 @@ bool harq_proc::new_tx(tti_point tti_tx_, max_retx = max_retx_; tti_tx = tti_tx_; tti_ack = tti_ack_; - rbgmask = rbgmask_; + prbs_ = grant; tb[0].ndi = !tb[0].ndi; tb[0].mcs = mcs; tb[0].tbs = tbs; @@ -65,22 +65,38 @@ bool harq_proc::new_tx(tti_point tti_tx_, return true; } -bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_, const rbgmask_t& rbgmask_, int* mcs, int* tbs) +bool harq_proc::set_tbs(uint32_t tbs) { - if (empty() or rbgmask.count() != rbgmask.count()) { + if (empty() or nof_retx() > 0) { + return false; + } + tb[0].tbs = tbs; + return true; +} + +bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_, const prb_grant& grant) +{ + if (grant.is_alloc_type0() != prbs_.is_alloc_type0() or + (grant.is_alloc_type0() and grant.rbgs().count() != prbs_.rbgs().count()) or + (grant.is_alloc_type1() and grant.prbs().length() == prbs_.prbs().length())) { + return false; + } + if (new_retx(tti_tx_, tti_ack_)) { + prbs_ = grant; + return true; + } + return false; +} + +bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_) +{ + if (empty()) { return false; } tti_tx = tti_tx_; tti_ack = tti_ack_; - rbgmask = rbgmask_; tb[0].ack_state = false; tb[0].n_rtx++; - if (mcs != nullptr) { - *mcs = tb[0].mcs; - } - if (tbs != nullptr) { - *tbs = tb[0].tbs; - } return true; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 023a81eef..87371aed4 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -55,10 +55,10 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, saved_dfs_tree.clear(); alloc_record record; - record.ue = user; - record.aggr_idx = aggr_idx; - record.search_space_id = search_space_id; - record.alloc_type = alloc_type; + record.ue = user; + record.aggr_idx = aggr_idx; + record.ss_id = search_space_id; + record.alloc_type = alloc_type; if (record.alloc_type == pdcch_grant_type_t::ul_data) { record.idx = pdcch_ul_list.size(); pdcch_ul_list.emplace_back(); @@ -158,7 +158,6 @@ bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_d // Allocation successful node.total_mask |= node.current_mask; alloc_dfs.push_back(node); - // set new DCI position if (record.alloc_type == pdcch_grant_type_t::ul_data) { pdcch_ul_t& pdcch_ul = pdcch_ul_list[record.idx]; pdcch_ul.dci.ctx.location = node.dci_pos; @@ -176,9 +175,9 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor { switch (record.alloc_type) { case pdcch_grant_type_t::dl_data: - return record.ue->cfg->cce_pos_list(record.search_space_id)[slot_idx][record.aggr_idx]; + return record.ue->cfg->cce_pos_list(record.ss_id)[slot_idx][record.aggr_idx]; case pdcch_grant_type_t::ul_data: - return record.ue->cfg->cce_pos_list(record.search_space_id)[slot_idx][record.aggr_idx]; + return record.ue->cfg->cce_pos_list(record.ss_id)[slot_idx][record.aggr_idx]; default: break; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy.cc b/srsenb/src/stack/mac/nr/sched_nr_phy.cc index 4652db3a1..ddc1b3566 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy.cc @@ -17,171 +17,68 @@ namespace srsenb { namespace sched_nr_impl { -/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P -uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2) -{ - srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size"); - if (bwp_nof_prb <= 36) { - return config_1_or_2 ? 2 : 4; - } - if (bwp_nof_prb <= 72) { - return config_1_or_2 ? 4 : 8; - } - if (bwp_nof_prb <= 144) { - return config_1_or_2 ? 8 : 16; - } - return 16; -} - -/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs -uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2) -{ - uint32_t P = get_P(bwp_nof_prb, config1_or_2); - return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P); -} - -uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx) -{ - uint32_t P = get_P(bwp_nof_prb, config1_or_2); - uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2); - if (rbg_idx == 0) { - return P - (bwp_start % P); - } - if (rbg_idx == nof_rbgs - 1) { - uint32_t ret = (bwp_start + bwp_nof_prb) % P; - return ret > 0 ? ret : P; - } - return P; -} - -void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran::span prbs) -{ - uint32_t count = 0; - for (uint32_t rbg = 0; rbg < bitmap.size(); ++rbg) { - bool val = bitmap.test(rbg); - uint32_t rbg_size = get_rbg_size(bwp_nof_prb, 0, true, rbg); - for (uint32_t prb_idx = count; prb_idx < count + rbg_size; ++prb_idx) { - prbs[prb_idx] = val; - } - } -} - -srsran::interval find_first_interval(const rbgmask_t& mask) -{ - int rb_start = mask.find_lowest(0, mask.size()); - if (rb_start != -1) { - int rb_end = mask.find_lowest(rb_start + 1, mask.size(), false); - return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)}; - } - return {}; -} - -int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb) -{ - srsran::interval interv = find_first_interval(bitmap); - srsran_assert(interv.length() == bitmap.count(), "Trying to acquire riv for non-contiguous bitmap"); - return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length()); -} - -rbg_interval find_empty_rbg_interval(const pdsch_bitmap& in_mask, uint32_t max_size) -{ - rbg_interval max_interv; - - for (size_t n = 0; n < in_mask.size();) { - int pos = in_mask.find_lowest(n, in_mask.size(), false); - if (pos < 0) { - break; - } - - size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size); - int pos2 = in_mask.find_lowest(pos + 1, max_pos, true); - rbg_interval interv(pos, pos2 < 0 ? max_pos : pos2); - if (interv.length() >= max_size) { - return interv; - } - if (interv.length() > max_interv.length()) { - max_interv = interv; - } - n = interv.stop(); - } - return max_interv; -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_rar(rbg_interval rbginterv, const bwp_params& cell, srsran_dci_dl_nr_t& dci) +bool fill_dci_rar(prb_interval interv, const bwp_params& cell, srsran_dci_dl_nr_t& dci) { dci.mcs = 5; return true; } template -void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const bwp_params& bwp_cfg, DciDlOrUl& dci) +void fill_dci_common(const slot_ue& ue, const bwp_params& bwp_cfg, DciDlOrUl& dci) { const static uint32_t rv_idx[4] = {0, 2, 3, 1}; - // Note: PDCCH DCI position already filled at this point - dci.bwp_id = ue.bwp_id; - dci.cc_id = ue.cc; - dci.freq_domain_assigment = bitmap_to_riv(bitmap, bwp_cfg.cfg.rb_width); - dci.ctx.rnti = ue.rnti; - dci.ctx.rnti_type = srsran_rnti_type_c; - dci.tpc = 1; + + dci.bwp_id = ue.bwp_id; + dci.cc_id = ue.cc; + dci.tpc = 1; // harq harq_proc* h = std::is_same::value ? ue.h_dl : ue.h_ul; dci.pid = h->pid; dci.ndi = h->ndi(); dci.mcs = h->mcs(); dci.rv = rv_idx[h->nof_retx() % 4]; -} - -void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci) -{ - fill_dci_common(ue, rbgmask, bwp_cfg, dci); -} - -void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& bwp_cfg, srsran_dci_ul_nr_t& dci) -{ - fill_dci_common(ue, rbgmask, bwp_cfg, dci); -} - -void fill_sch_ue_common(const slot_ue& ue, - const rbgmask_t& rbgmask, - const bwp_params& bwp_cfg, - srsran_sch_cfg_nr_t& sch) -{ - sch.grant.rnti_type = srsran_rnti_type_c; - sch.grant.rnti = ue.rnti; - sch.grant.nof_layers = 1; - sch.grant.nof_prb = bwp_cfg.cfg.rb_width; -} - -void fill_pdsch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& cc_cfg, srsran_sch_cfg_nr_t& sch) -{ - fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); - sch.grant.k = ue.cc_cfg->pdsch_res_list[0].k0; - sch.grant.dci_format = srsran_dci_format_nr_1_0; -} - -void fill_pusch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const bwp_params& cc_cfg, srsran_sch_cfg_nr_t& sch) -{ - fill_sch_ue_common(ue, rbgmask, cc_cfg, sch); - sch.grant.k = ue.cc_cfg->pusch_res_list[0].k2; - sch.grant.dci_format = srsran_dci_format_nr_0_1; -} - -pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbgs, uint32_t tbs) -{ - if (ue.cfg->cfg().pucch.enabled) { - for (uint32_t i = 0; i < SRSRAN_PUCCH_NR_MAX_NOF_SETS; ++i) { - const auto& rset = ue.cfg->cfg().pucch.sets[i]; - if (rset.max_payload_size >= tbs) { - for (uint32_t sid = 0; sid < rset.nof_resources; ++sid) { - return pucch_resource_grant{ue.rnti, i, sid}; - } - } - } + // PRB assignment + const prb_grant& grant = h->prbs(); + if (grant.is_alloc_type0()) { + dci.freq_domain_assigment = grant.rbgs().to_uint64(); + } else { + dci.freq_domain_assigment = + srsran_ra_nr_type1_riv(bwp_cfg.cfg.rb_width, grant.prbs().start(), grant.prbs().length()); } - return pucch_resource_grant{SRSRAN_INVALID_RNTI, 0, 0}; + dci.time_domain_assigment = 0; +} + +void fill_dl_dci_ue_fields(const slot_ue& ue, + const bwp_params& bwp_cfg, + uint32_t ss_id, + srsran_dci_location_t dci_pos, + srsran_dci_dl_nr_t& dci) +{ + // Note: DCI location may not be the final one, as scheduler may rellocate the UE PDCCH. However, the remaining DCI + // params are independent of the exact DCI location + bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); + srsran_assert(ret, "Invalid DL DCI format"); + + fill_dci_common(ue, bwp_cfg, dci); + if (dci.ctx.format == srsran_dci_format_nr_1_0) { + dci.harq_feedback = ue.cfg->phy().harq_ack.dl_data_to_ul_ack[ue.pdsch_tti.sf_idx()] - 1; + } else { + dci.harq_feedback = ue.pdsch_tti.sf_idx(); + } +} + +void fill_ul_dci_ue_fields(const slot_ue& ue, + const bwp_params& bwp_cfg, + uint32_t ss_id, + srsran_dci_location_t dci_pos, + srsran_dci_ul_nr_t& dci) +{ + bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); + srsran_assert(ret, "Invalid DL DCI format"); + + fill_dci_common(ue, bwp_cfg, dci); } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb.cc b/srsenb/src/stack/mac/nr/sched_nr_rb.cc new file mode 100644 index 000000000..d03af3592 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_rb.cc @@ -0,0 +1,106 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/nr/sched_nr_rb.h" + +namespace srsenb { +namespace sched_nr_impl { + +/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P +uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2) +{ + srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size"); + if (bwp_nof_prb <= 36) { + return config_1_or_2 ? 2 : 4; + } + if (bwp_nof_prb <= 72) { + return config_1_or_2 ? 4 : 8; + } + if (bwp_nof_prb <= 144) { + return config_1_or_2 ? 8 : 16; + } + return 16; +} + +/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs +uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2) +{ + uint32_t P = get_P(bwp_nof_prb, config1_or_2); + return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P); +} + +uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx) +{ + uint32_t P = get_P(bwp_nof_prb, config1_or_2); + uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2); + if (rbg_idx == 0) { + return P - (bwp_start % P); + } + if (rbg_idx == nof_rbgs - 1) { + uint32_t ret = (bwp_start + bwp_nof_prb) % P; + return ret > 0 ? ret : P; + } + return P; +} + +bwp_rb_bitmap::bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2) : + prbs_(bwp_nof_prbs), + rbgs_(get_nof_rbgs(bwp_nof_prbs, bwp_prb_start_, config1_or_2)), + bwp_prb_start(bwp_prb_start_), + P_(get_P(bwp_nof_prbs, config1_or_2)), + Pnofbits(log2(P_)), + first_rbg_size(get_rbg_size(bwp_nof_prbs, bwp_prb_start_, config1_or_2, 0)) +{} + +uint32_t bwp_rb_bitmap::prb_to_rbg_idx(uint32_t prb_idx) const +{ + return ((prb_idx + P_ - first_rbg_size) >> Pnofbits); +} + +void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_bitmap& grant) +{ + int idx = 0; + do { + idx = grant.find_lowest(idx, grant.size(), true); + if (idx < 0) { + return; + } + uint32_t rbg_idx = prb_to_rbg_idx(idx); + rbgs_.set(rbg_idx, true); + idx++; + } while (idx != (int)prbs_.size()); +} + +void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_interval& grant) +{ + uint32_t rbg_start = prb_to_rbg_idx(grant.start()); + uint32_t rbg_stop = std::min(prb_to_rbg_idx(grant.stop() - 1) + 1u, (uint32_t)rbgs_.size()); + rbgs_.fill(rbg_start, rbg_stop); +} + +void bwp_rb_bitmap::add_rbgs_to_prbs(const rbg_bitmap& grant) +{ + int idx = 0; + do { + idx = grant.find_lowest(idx, grant.size(), true); + if (idx < 0) { + return; + } + uint32_t prb_idx = (idx - 1) * P_ + first_rbg_size; + uint32_t prb_end = std::min(prb_idx + ((idx == 0) ? first_rbg_size : P_), (uint32_t)prbs_.size()); + prbs_.fill(prb_idx, prb_end); + idx++; + } while (idx != (int)prbs_.size()); +} + +} // namespace sched_nr_impl +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index efb271b0b..ceefc7e72 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -19,8 +19,8 @@ namespace sched_nr_impl { #define NUMEROLOGY_IDX 0 bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) : - dl_rbgs(bwp_cfg_.N_rbg), - ul_rbgs(bwp_cfg_.N_rbg), + dl_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1), + ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1), slot_idx(slot_idx_), cfg(&bwp_cfg_), is_dl(srsran_tdd_nr_is_dl(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)), @@ -41,8 +41,8 @@ void bwp_slot_grid::reset() coreset->reset(); } } - dl_rbgs.reset(); - ul_rbgs.reset(); + dl_prbs.reset(); + ul_prbs.reset(); dl_pdcchs.clear(); ul_pdcchs.clear(); pucchs.clear(); @@ -63,7 +63,7 @@ bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx, const srsenb::sched_nr_impl::pending_rar_t& rar, - srsenb::sched_nr_impl::rbg_interval interv, + prb_interval interv, uint32_t nof_grants) { static const uint32_t msg3_nof_prbs = 3; @@ -77,8 +77,8 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t } // Check DL RB collision - rbgmask_t& pdsch_mask = bwp_pdcch_slot.dl_rbgs; - rbgmask_t dl_mask(pdsch_mask.size()); + const prb_bitmap& pdsch_mask = bwp_pdcch_slot.dl_prbs.prbs(); + prb_bitmap dl_mask(pdsch_mask.size()); dl_mask.fill(interv.start(), interv.stop()); if ((pdsch_mask & dl_mask).any()) { logger.debug("SCHED: Provided RBG mask collides with allocation previously made."); @@ -88,7 +88,7 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t // Check Msg3 RB collision uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants; uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false)); - rbg_interval msg3_rbgs = find_empty_rbg_interval(bwp_msg3_slot.ul_rbgs, total_ul_nof_rbgs); + prb_interval msg3_rbgs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs); if (msg3_rbgs.length() < total_ul_nof_rbgs) { logger.debug("SCHED: No space in PUSCH for Msg3."); return alloc_result::sch_collision; @@ -112,12 +112,12 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t } // RAR allocation successful. - bwp_pdcch_slot.dl_rbgs.fill(interv.start(), interv.stop()); + bwp_pdcch_slot.dl_prbs.add(interv); return alloc_result::success; } -alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant) { if (ue.h_dl == nullptr) { logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); @@ -135,49 +135,65 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_ma logger.warning("SCHED: Maximum number of DL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pdsch_mask = bwp_pdsch_slot.dl_rbgs; - if ((pdsch_mask & dl_mask).any()) { + if (bwp_pdcch_slot.dl_prbs.collides(dl_grant)) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, search_space_id = 1; - uint32_t coreset_id = ue.cfg->cfg().pdcch.search_space[search_space_id].coreset_id; - if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, search_space_id, &ue)) { + + // Find space in PUCCH + // TODO + + // Find space and allocate PDCCH + const uint32_t aggr_idx = 2, ss_id = 1; + uint32_t coreset_id = ue.cfg->phy().pdcch.search_space[ss_id].coreset_id; + if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, ss_id, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } - int mcs = -1, tbs = -1; + // Allocate HARQ if (ue.h_dl->empty()) { - mcs = 20; - tbs = 100; - bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_mask, mcs, tbs, 4); + int mcs = 20; + int tbs = 100; + bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_grant, mcs, tbs, 4); srsran_assert(ret, "Failed to allocate DL HARQ"); } else { - bool ret = ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_mask, &mcs, &tbs); + bool ret = ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_grant); srsran_assert(ret, "Failed to allocate DL HARQ retx"); } - pucch_resource_grant pucch_res = find_pucch_resource(ue, bwp_uci_slot.ul_rbgs, tbs); - if (pucch_res.rnti != SRSRAN_INVALID_RNTI) { - // Could not find space in PUCCH for HARQ-ACK - bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); - return alloc_result::no_cch_space; - } - // Allocation Successful + + // Generate PDCCH pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); - fill_dci_ue_cfg(ue, dl_mask, *bwp_grid.cfg, pdcch.dci); - pdsch_mask |= dl_mask; + fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); + pdcch.dci.pucch_resource = 0; + pdcch.dci.dai = std::count_if(bwp_uci_slot.pucchs.begin(), bwp_uci_slot.pucchs.end(), [&ue](const pucch_t& p) { + return p.uci_cfg.pucch.rnti == ue.rnti; + }); + + // Generate PUCCH bwp_uci_slot.pucchs.emplace_back(); - pucch_grant& pucch = bwp_uci_slot.pucchs.back(); - pucch.resource = pucch_res; - bwp_uci_slot.ul_rbgs.set( - ue.cfg->cfg().pucch.sets[pucch_res.resource_set_id].resources[pucch_res.resource_id].starting_prb); + pucch_t& pucch = bwp_uci_slot.pucchs.back(); + pucch.uci_cfg.pucch.rnti = ue.rnti; + + // Generate PDSCH + bwp_pdsch_slot.dl_prbs |= dl_grant; + bwp_pdsch_slot.pdschs.emplace_back(); + pdsch_t& pdsch = bwp_pdsch_slot.pdschs.back(); + srsran_slot_cfg_t slot_cfg; + slot_cfg.idx = ue.pdsch_tti.sf_idx(); + bool ret = ue.cfg->phy().get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); + srsran_assert(ret, "Error converting DCI to grant"); + if (ue.h_dl->nof_retx() == 0) { + ue.h_dl->set_tbs(pdsch.sch.grant.tb[0].tbs); // update HARQ with correct TBS + } else { + srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx"); + } return alloc_result::success; } -alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_mask) { if (ue.h_ul == nullptr) { logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); @@ -194,33 +210,32 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_ma logger.warning("SCHED: Maximum number of UL allocations reached"); return alloc_result::no_grant_space; } - rbgmask_t& pusch_mask = bwp_pusch_slot.ul_rbgs; + const rbg_bitmap& pusch_mask = bwp_pusch_slot.ul_prbs.rbgs(); if ((pusch_mask & ul_mask).any()) { return alloc_result::sch_collision; } - const uint32_t aggr_idx = 2, search_space_id = 1; - uint32_t coreset_id = ue.cfg->cfg().pdcch.search_space[search_space_id].coreset_id; - if (not bwp_pdcch_slot.coresets[coreset_id].value().alloc_dci( - pdcch_grant_type_t::ul_data, aggr_idx, search_space_id, &ue)) { + const uint32_t aggr_idx = 2, ss_id = 1; + uint32_t coreset_id = ue.cfg->phy().pdcch.search_space[ss_id].coreset_id; + if (not bwp_pdcch_slot.coresets[coreset_id].value().alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, ss_id, &ue)) { // Could not find space in PDCCH return alloc_result::no_cch_space; } - int mcs = -1, tbs = -1; if (ue.h_ul->empty()) { - mcs = 20; - tbs = 100; + int mcs = 20; + int tbs = 100; bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); srsran_assert(ret, "Failed to allocate UL HARQ"); } else { - srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask, &mcs, &tbs), - "Failed to allocate UL HARQ retx"); + srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask), "Failed to allocate UL HARQ retx"); } // Allocation Successful + // Generate PDCCH pdcch_ul_t& pdcch = pdcchs.back(); - fill_dci_ue_cfg(ue, ul_mask, *bwp_grid.cfg, pdcch.dci); - pusch_mask |= ul_mask; + fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); + // Generate PUSCH + bwp_pusch_slot.ul_prbs.add(ul_mask); return alloc_result::success; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index e18807a6f..79e40a2b9 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -196,12 +196,9 @@ bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs; dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs; - - ul_res.pucch.resize(pdcch_bwp_slot.pucchs.size()); - for (uint32_t i = 0; i < pdcch_bwp_slot.pucchs.size(); ++i) { - ul_res.pucch[i].uci_cfg.pucch.rnti = pdcch_bwp_slot.pucchs[i].resource.rnti; - ul_res.pucch[i].uci_cfg.pucch.resource_id = pdcch_bwp_slot.pucchs[i].resource.resource_id; - } + dl_res.pdsch = pdcch_bwp_slot.pdschs; + ul_res.pucch = pdcch_bwp_slot.pucchs; + ul_res.pusch = pdcch_bwp_slot.puschs; // clear up BWP slot pdcch_bwp_slot.reset(); diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index 1e1b70747..113683f07 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -13,3 +13,11 @@ target_link_libraries(sched_nr_test ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_test(sched_nr_test sched_nr_test) + +add_executable(sched_nr_prb_test sched_nr_prb_test.cc) +target_link_libraries(sched_nr_prb_test + srsgnb_mac + srsran_common + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES}) +add_test(sched_nr_prb_test sched_nr_prb_test) diff --git a/srsenb/test/mac/nr/sched_nr_prb_test.cc b/srsenb/test/mac/nr/sched_nr_prb_test.cc new file mode 100644 index 000000000..71bc78776 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_prb_test.cc @@ -0,0 +1,130 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/nr/sched_nr_rb.h" +#include "srsran/common/test_common.h" + +using namespace srsenb; +using namespace srsenb::sched_nr_impl; + +void test_bwp_prb_grant() +{ + // TEST: default ctor + prb_grant grant; + TESTASSERT(grant.is_alloc_type1()); + TESTASSERT(grant.prbs().length() == 0); + + // TEST: assignment of RBGs + rbg_bitmap rbgs(18); + rbgs.set(1); + grant = rbgs; + TESTASSERT(grant.is_alloc_type0() and grant.rbgs().count() == 1); + + // TEST: assignment of PRBs + prb_interval prb_interv(2, 5); + grant = prb_interv; + TESTASSERT(grant.is_alloc_type1() and grant.prbs().length() == 3); + + // TEST: non-default ctor + prb_grant grant2(prb_interv), grant3(rbgs); + TESTASSERT(grant2.is_alloc_type1() and grant2.prbs().length() == 3); + TESTASSERT(grant3.is_alloc_type0() and grant3.rbgs().count() == 1); + + // TEST: copy ctor + prb_grant grant4(grant2), grant5(grant3); + TESTASSERT(grant4.is_alloc_type1() and grant4.prbs().length() == 3); + TESTASSERT(grant5.is_alloc_type0() and grant5.rbgs().count() == 1); + + // TEST: copy assignment + grant = grant3; + TESTASSERT(grant.is_alloc_type0() and grant.rbgs().count() == 1); + grant = grant2; + TESTASSERT(grant.is_alloc_type1() and grant.prbs().length() == 3); +} + +void test_bwp_rb_bitmap() +{ + bwp_rb_bitmap rb_bitmap(275, 0, true); + + TESTASSERT(rb_bitmap.P() == 16); + TESTASSERT(rb_bitmap.rbgs().none()); + TESTASSERT(rb_bitmap.prbs().none()); + TESTASSERT(rb_bitmap.prbs().size() == 275 and rb_bitmap.nof_prbs() == 275); + TESTASSERT(rb_bitmap.rbgs().size() == 18 and rb_bitmap.nof_rbgs() == 18); + + rb_bitmap.add(prb_interval{0, 1}); + TESTASSERT(rb_bitmap.prbs().count() == 1 and rb_bitmap.prbs().test(0)); + TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0)); + rb_bitmap.add(prb_interval{2, 4}); + TESTASSERT(rb_bitmap.prbs().count() == 3 and rb_bitmap.prbs().test(2) and not rb_bitmap.prbs().test(1)); + TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0)); + + prb_bitmap prbs(rb_bitmap.nof_prbs()); + prbs.set(1); + prbs.set(2); + prbs.set(15); + rb_bitmap.add(prbs); + TESTASSERT(rb_bitmap.prbs().count() == 5 and rb_bitmap.prbs().test(1) and rb_bitmap.prbs().test(15)); + TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0)); + prbs.set(16); + rb_bitmap |= prbs; + TESTASSERT(rb_bitmap.prbs().count() == 6 and rb_bitmap.prbs().test(16)); + TESTASSERT(rb_bitmap.rbgs().count() == 2 and rb_bitmap.rbgs().test(1)); + + rbg_bitmap rbgs(rb_bitmap.nof_rbgs()); + rbgs.set(3); + rbgs.set(17); + rb_bitmap |= rbgs; + TESTASSERT(rb_bitmap.prbs().count() == (6 + 16 + 3) and rb_bitmap.prbs().test(rb_bitmap.nof_prbs() - 1)); + TESTASSERT(rb_bitmap.rbgs().count() == 4 and rb_bitmap.rbgs().test(3) and rb_bitmap.rbgs().test(17)); + rbgs.set(0); + rb_bitmap |= rbgs; + TESTASSERT(rb_bitmap.prbs().count() == (16 + 1 + 16 + 3) and rb_bitmap.prbs().test(rb_bitmap.nof_prbs() - 1)); + TESTASSERT(rb_bitmap.rbgs().count() == 4 and rb_bitmap.rbgs().test(3) and rb_bitmap.rbgs().test(17)); + + // TEST: collides operator + TESTASSERT(rb_bitmap.collides(rbgs)); + TESTASSERT(rb_bitmap.collides(prb_interval{0, 2})); +} + +void test_bwp_rb_bitmap_search() +{ + bwp_rb_bitmap rb_bitmap(275, 0, true); + + prb_interval prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 5); + TESTASSERT(prbs == prb_interval(0, 5)); + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size()); + TESTASSERT(prbs == prb_interval(0, rb_bitmap.prbs().size())); + + rb_bitmap |= prb_interval{1, 5}; + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size()); + TESTASSERT(prbs == prb_interval(5, rb_bitmap.prbs().size())); + + rb_bitmap |= prb_interval{16, 32}; + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size()); + TESTASSERT(prbs == prb_interval(32, rb_bitmap.prbs().size())); + + rb_bitmap |= prb_interval{270, 275}; + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size()); + TESTASSERT(prbs == prb_interval(32, 270)); + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 1); + TESTASSERT(prbs == prb_interval(0, 1)); + prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 5); + TESTASSERT(prbs == prb_interval(5, 10)); +} + +int main() +{ + test_bwp_prb_grant(); + test_bwp_rb_bitmap(); + test_bwp_rb_bitmap_search(); +} diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index e6977674c..ceef7b10b 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -49,11 +49,11 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() cell_cfg.tdd.pattern2.period_ms = 0; cell_cfg.bwps.resize(1); - cell_cfg.bwps[0].pdcch.coreset_present[0] = true; - cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); - cell_cfg.bwps[0].pdcch.coreset_present[1] = true; - cell_cfg.bwps[0].pdcch.coreset[1] = default_phy_cfg.pdcch.coreset[1]; + cell_cfg.bwps[0].pdcch = default_phy_cfg.pdcch; + cell_cfg.bwps[0].pdsch = default_phy_cfg.pdsch; + cell_cfg.bwps[0].pdcch.coreset_present[0] = true; + cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); cell_cfg.bwps[0].pdcch.search_space_present[0] = true; auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; ss.id = 0; @@ -67,8 +67,6 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() ss.nof_candidates[4] = 0; ss.nof_formats = 1; ss.formats[0] = srsran_dci_format_nr_1_0; - cell_cfg.bwps[0].pdcch.search_space_present[1] = true; - cell_cfg.bwps[0].pdcch.search_space[1] = default_phy_cfg.pdcch.search_space[1]; cell_cfg.bwps[0].pdcch.ra_search_space_present = true; cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; From 323703c2f3fbfa7da33f75b8dab41c62357d7327 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 12 Jul 2021 09:52:47 +0100 Subject: [PATCH 55/59] sched,nr: measure latency of sched nr in test --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 3 +- srsenb/src/stack/mac/nr/sched_nr_bwp.cc | 2 +- srsenb/test/mac/nr/sched_nr_test.cc | 31 +++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 23b1093cb..a32dd5832 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -58,7 +58,8 @@ public: }; struct cell_cfg_t { - srsran_tdd_config_nr_t tdd = {}; + srsran_carrier_nr_t carrier = {}; + srsran_tdd_config_nr_t tdd = {}; srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc index 223d05294..1e9a4b38f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -29,7 +29,7 @@ ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_ for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { ret = alloc_result::invalid_coderate; uint32_t start_prb_idx = 0; - for (uint32_t nprb = 1; nprb < bwp_cfg->N_rbg and ret == alloc_result::invalid_coderate; ++nprb) { + for (uint32_t nprb = 1; nprb < bwp_cfg->cfg.rb_width and ret == alloc_result::invalid_coderate; ++nprb) { prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx); start_prb_idx = interv.stop(); if (interv.length() == nprb) { diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index ceef7b10b..c3d058131 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -15,6 +15,7 @@ #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/test_common.h" #include "srsran/common/thread_pool.h" +#include namespace srsenb { @@ -39,18 +40,13 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg() { sched_nr_interface::cell_cfg_t cell_cfg{}; - cell_cfg.tdd.pattern1.period_ms = 10; - cell_cfg.tdd.pattern1.nof_dl_slots = 6; - cell_cfg.tdd.pattern1.nof_dl_symbols = 0; - cell_cfg.tdd.pattern1.nof_ul_slots = 4; - cell_cfg.tdd.pattern1.nof_ul_symbols = 0; - - // Disable pattern 2 - cell_cfg.tdd.pattern2.period_ms = 0; + cell_cfg.carrier = default_phy_cfg.carrier; + cell_cfg.tdd = default_phy_cfg.tdd; cell_cfg.bwps.resize(1); - cell_cfg.bwps[0].pdcch = default_phy_cfg.pdcch; - cell_cfg.bwps[0].pdsch = default_phy_cfg.pdsch; + cell_cfg.bwps[0].pdcch = default_phy_cfg.pdcch; + cell_cfg.bwps[0].pdsch = default_phy_cfg.pdsch; + cell_cfg.bwps[0].rb_width = default_phy_cfg.carrier.nof_prb; cell_cfg.bwps[0].pdcch.coreset_present[0] = true; cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); @@ -158,6 +154,7 @@ void sched_nr_cfg_serialized_test() sched_tester.add_user(0x46, uecfg, 0); + auto tp1 = std::chrono::steady_clock::now(); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; @@ -174,9 +171,13 @@ void sched_nr_cfg_serialized_test() TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti_tx).sf_idx()) or dl_res.pdcch_dl.size() == 1); } } + auto tp2 = std::chrono::steady_clock::now(); tasks.print_results(); TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); + + uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); + printf("Total time taken per slot: %f\n", microsecs / (float)max_nof_ttis); } void sched_nr_cfg_parallel_cc_test() @@ -193,6 +194,7 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched_tester.add_user(0x46, uecfg, 0); + auto tp1 = std::chrono::steady_clock::now(); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; @@ -210,11 +212,15 @@ void sched_nr_cfg_parallel_cc_test() }); } } + auto tp2 = std::chrono::steady_clock::now(); tasks.wait_task_finish(); tasks.print_results(); TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); + + uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); + printf("Total time taken per slot [usec]: %f\n", microsecs / (float)max_nof_ttis); } void sched_nr_cfg_parallel_sf_test() @@ -233,6 +239,7 @@ void sched_nr_cfg_parallel_sf_test() sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched.ue_cfg(0x46, uecfg); + auto tp1 = std::chrono::steady_clock::now(); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); tasks.start_slot(tti, nof_sectors); @@ -246,10 +253,14 @@ void sched_nr_cfg_parallel_sf_test() }); } } + auto tp2 = std::chrono::steady_clock::now(); tasks.wait_task_finish(); tasks.print_results(); + + uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); + printf("Total time taken per slot [usec]: %f\n", microsecs / (float)max_nof_ttis); } } // namespace srsenb From 1535e6b20513050256e4fe2fa0049ae53bac5ada Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 14 Jul 2021 10:14:07 +0100 Subject: [PATCH 56/59] sched,nr: extend sched nr testing suite. restrict paralllelization for correct DAI generation --- lib/src/common/phy_cfg_nr_default.cc | 2 +- .../nr/{sched_nr_phy.h => sched_nr_helpers.h} | 6 +- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 4 +- srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h | 10 +- srsenb/hdr/stack/mac/nr/sched_nr_worker.h | 12 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/sched_nr.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 2 +- .../{sched_nr_phy.cc => sched_nr_helpers.cc} | 2 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 18 +-- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 14 +- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 74 ++++++++-- srsenb/test/mac/nr/CMakeLists.txt | 2 +- srsenb/test/mac/nr/sched_nr_sim_ue.cc | 133 +++++++++++------- srsenb/test/mac/nr/sched_nr_sim_ue.h | 63 +++++++-- srsenb/test/mac/nr/sched_nr_test.cc | 77 ++++++---- .../test/mac/nr/sched_nr_ue_ded_test_suite.cc | 54 +++++++ .../test/mac/nr/sched_nr_ue_ded_test_suite.h | 24 ++++ 18 files changed, 372 insertions(+), 129 deletions(-) rename srsenb/hdr/stack/mac/nr/{sched_nr_phy.h => sched_nr_helpers.h} (92%) rename srsenb/src/stack/mac/nr/{sched_nr_phy.cc => sched_nr_helpers.cc} (97%) create mode 100644 srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc create mode 100644 srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 511045284..642a272ba 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -163,7 +163,7 @@ void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, const srsran_tdd_config_nr_t& tdd_cfg) { // Generate as many entries as DL slots - harq.nof_dl_data_to_ul_ack = SRSRAN_MAX(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); + harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); // Set PDSCH to ACK timing delay to 4 or more for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h similarity index 92% rename from srsenb/hdr/stack/mac/nr/sched_nr_phy.h rename to srsenb/hdr/stack/mac/nr/sched_nr_helpers.h index 76141c847..019628cd1 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_PHY_H -#define SRSRAN_SCHED_NR_PHY_H +#ifndef SRSRAN_SCHED_NR_HELPERS_H +#define SRSRAN_SCHED_NR_HELPERS_H #include "sched_nr_cfg.h" @@ -41,4 +41,4 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_PHY_H +#endif // SRSRAN_SCHED_NR_HELPERS_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index a32dd5832..b934d7b6c 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -68,9 +68,7 @@ public: }; struct ue_cc_cfg_t { - bool active = false; - pdsch_td_res_alloc_list pdsch_res_list{1}; - pusch_td_res_alloc_list pusch_res_list{1}; + bool active = false; }; struct ue_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index ddbaf82be..ceddac4a1 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -15,9 +15,9 @@ #include "../sched_common.h" #include "lib/include/srsran/adt/circular_array.h" +#include "sched_nr_helpers.h" #include "sched_nr_interface.h" #include "sched_nr_pdcch.h" -#include "sched_nr_phy.h" #include "sched_nr_ue.h" namespace srsenb { @@ -33,6 +33,12 @@ using slot_coreset_list = std::array; +struct harq_ack_t { + const srsran::phy_cfg_nr_t* phy_cfg; + srsran_harq_ack_resource_t res; +}; +using harq_ack_list_t = srsran::bounded_vector; + struct bwp_slot_grid { uint32_t slot_idx; const bwp_params* cfg; @@ -44,8 +50,8 @@ struct bwp_slot_grid { pdcch_ul_list_t ul_pdcchs; pdsch_list_t pdschs; slot_coreset_list coresets; - pucch_list_t pucchs; pusch_list_t puschs; + harq_ack_list_t pending_acks; bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_); diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index f2a44580d..0548dedef 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -43,9 +43,11 @@ public: private: void alloc_dl_ues(); void alloc_ul_ues(); + void log_result() const; const sched_cell_params& cfg; serv_cell_ctxt& cell; + srslog::basic_logger& logger; tti_point tti_rx; bwp_slot_allocator bwp_alloc; @@ -73,12 +75,14 @@ public: void start_slot(tti_point tti_rx, srsran::move_callback process_feedback); bool run_slot(tti_point tti_rx, uint32_t cc); void release_slot(tti_point tti_rx); - bool get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); + bool save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res); private: - const sched_params& cfg; - ue_map_t& ue_db; - std::mutex ue_db_mutex; + const sched_params& cfg; + ue_map_t& ue_db; + srslog::basic_logger& logger; + + std::mutex ue_db_mutex; std::vector > slot_worker_ctxts; diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 0c3a2b2d5..df28c36a2 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -7,6 +7,6 @@ # set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc - sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc sched_nr_rb.cc) + sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index c25ca4bfe..90caf0ca1 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -197,7 +197,7 @@ int sched_nr::generate_slot_result(tti_point pdcch_tti, uint32_t cc) // Copy results to intermediate buffer dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc); ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc); - sched_workers->get_sched_result(pdcch_tti, cc, dl_res, ul_res); + sched_workers->save_sched_result(pdcch_tti, cc, dl_res, ul_res); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 25e4f217a..89ad86a49 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -11,7 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc similarity index 97% rename from srsenb/src/stack/mac/nr/sched_nr_phy.cc rename to srsenb/src/stack/mac/nr/sched_nr_helpers.cc index ddc1b3566..e9b44bf7f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index ceefc7e72..c4e7b0567 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -11,7 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" namespace srsenb { namespace sched_nr_impl { @@ -45,7 +45,7 @@ void bwp_slot_grid::reset() ul_prbs.reset(); dl_pdcchs.clear(); ul_pdcchs.clear(); - pucchs.clear(); + pending_acks.clear(); } bwp_res_grid::bwp_res_grid(const bwp_params& bwp_cfg_) : cfg(&bwp_cfg_) @@ -167,14 +167,16 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); pdcch.dci.pucch_resource = 0; - pdcch.dci.dai = std::count_if(bwp_uci_slot.pucchs.begin(), bwp_uci_slot.pucchs.end(), [&ue](const pucch_t& p) { - return p.uci_cfg.pucch.rnti == ue.rnti; - }); + pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(), + bwp_uci_slot.pending_acks.end(), + [&ue](const harq_ack_t& p) { return p.res.rnti == ue.rnti; }); + pdcch.dci.dai %= 4; // Generate PUCCH - bwp_uci_slot.pucchs.emplace_back(); - pucch_t& pucch = bwp_uci_slot.pucchs.back(); - pucch.uci_cfg.pucch.rnti = ue.rnti; + bwp_uci_slot.pending_acks.emplace_back(); + bwp_uci_slot.pending_acks.back().phy_cfg = &ue.cfg->phy(); + srsran_assert(ue.cfg->phy().get_pdsch_ack_resource(pdcch.dci, bwp_uci_slot.pending_acks.back().res), + "Error getting ack resource"); // Generate PDSCH bwp_pdsch_slot.dl_prbs |= dl_grant; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 59b5f979a..bd022efb9 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -58,11 +58,15 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_) sfu.cfg = &bwp_cfg; // copy cc-specific parameters and find available HARQs - sfu.cc_cfg = &uecfg_.carriers[cc]; - sfu.pdcch_tti = tti_rx + TX_ENB_DELAY; - sfu.pdsch_tti = sfu.pdcch_tti + sfu.cc_cfg->pdsch_res_list[0].k0; - sfu.pusch_tti = sfu.pdcch_tti + sfu.cc_cfg->pusch_res_list[0].k2; - sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1; + sfu.cc_cfg = &uecfg_.carriers[cc]; + sfu.pdcch_tti = tti_rx + TX_ENB_DELAY; + const uint32_t k0 = 0; + sfu.pdsch_tti = sfu.pdcch_tti + k0; + uint32_t k1 = + sfu.cfg->phy().harq_ack.dl_data_to_ul_ack[sfu.pdsch_tti.sf_idx() % sfu.cfg->phy().harq_ack.nof_dl_data_to_ul_ack]; + sfu.uci_tti = sfu.pdsch_tti + k1; + uint32_t k2 = k1; + sfu.pusch_tti = sfu.pdcch_tti + k2; sfu.dl_cqi = dl_cqi; sfu.ul_cqi = ul_cqi; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 79e40a2b9..b50517c73 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -11,12 +11,13 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" +#include "srsran/common/string_helpers.h" namespace srsenb { namespace sched_nr_impl { slot_cc_worker::slot_cc_worker(serv_cell_ctxt& cc_sched) : - cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid) + cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid), logger(srslog::fetch_basic_logger("MAC")) {} /// Called at the beginning of TTI in a locked context, to reserve available UE resources @@ -52,6 +53,9 @@ void slot_cc_worker::run() // TODO: Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion alloc_dl_ues(); alloc_ul_ues(); + + // Log CC scheduler result + log_result(); } void slot_cc_worker::end_tti() @@ -94,9 +98,37 @@ void slot_cc_worker::alloc_ul_ues() bwp_alloc.alloc_pusch(ue, ulmask); } +void slot_cc_worker::log_result() const +{ + const bwp_slot_grid& bwp_slot = cell.bwps[0].grid[tti_rx + TX_ENB_DELAY]; + for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) { + fmt::memory_buffer fmtbuf; + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to(fmtbuf, + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, dai={}, tti_pdsch={}, tti_ack={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + cell.cfg->cc, + ue.rnti, + ue.h_dl->pid, + ue.h_dl->nof_retx(), + pdcch.dci.dai, + ue.pdsch_tti, + ue.uci_tti); + } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { + fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}", cell.cfg->cc); + } else { + fmt::format_to(fmtbuf, "SCHED: unknown format"); + } + + logger.info("%s", srsran::to_c_str(fmtbuf)); + } +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : cfg(cfg_), ue_db(ue_db_) +sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : + cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger("MAC")) { for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { cell_grid_list.emplace_back(cfg.cells[cc]); @@ -186,22 +218,44 @@ void sched_worker_manager::release_slot(tti_point tti_rx_) std::unique_lock lock(sf_worker_ctxt.slot_mutex); sf_worker_ctxt.tti_rx = {}; if (sf_worker_ctxt.nof_workers_waiting > 0) { + lock.unlock(); sf_worker_ctxt.cvar.notify_one(); } } -bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) +bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) { - auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti]; + auto& bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti]; - dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs; - dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs; - dl_res.pdsch = pdcch_bwp_slot.pdschs; - ul_res.pucch = pdcch_bwp_slot.pucchs; - ul_res.pusch = pdcch_bwp_slot.puschs; + dl_res.pdcch_dl = bwp_slot.dl_pdcchs; + dl_res.pdcch_ul = bwp_slot.ul_pdcchs; + dl_res.pdsch = bwp_slot.pdschs; + ul_res.pusch = bwp_slot.puschs; + + // Generate PUCCH + srsran_pdsch_ack_nr_t ack = {}; + ack.nof_cc = not bwp_slot.pending_acks.empty(); + const srsran::phy_cfg_nr_t* phy_cfg = nullptr; + for (const harq_ack_t& pending_ack : bwp_slot.pending_acks) { + srsran_harq_ack_m_t ack_m = {}; + ack_m.resource = pending_ack.res; + ack_m.present = true; + srsran_harq_ack_insert_m(&ack, &ack_m); + phy_cfg = pending_ack.phy_cfg; + } + + if (phy_cfg != nullptr) { + srsran_slot_cfg_t slot_cfg{}; + slot_cfg.idx = pdcch_tti.sf_idx(); + ul_res.pucch.emplace_back(); + pucch_t& pucch = ul_res.pucch.back(); + if (not phy_cfg->get_pucch(slot_cfg, ack, pucch.pucch_cfg, pucch.uci_cfg, pucch.resource)) { + logger.error("Error getting UCI CFG"); + } + } // clear up BWP slot - pdcch_bwp_slot.reset(); + bwp_slot.reset(); return true; } diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index 113683f07..528a9e3e2 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc) +add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc sched_nr_ue_ded_test_suite.cc) target_link_libraries(sched_nr_test srsgnb_mac srsran_common diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index 8db2034e2..6c04b4378 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -11,6 +11,7 @@ */ #include "sched_nr_sim_ue.h" +#include "sched_nr_ue_ded_test_suite.h" #include "srsran/common/test_common.h" namespace srsenb { @@ -38,6 +39,23 @@ sched_nr_ue_sim::sched_nr_ue_sim(uint16_t rnti_, int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out) { update_dl_harqs(cc_out); + + for (uint32_t i = 0; i < cc_out.dl_cc_result->pdcch_dl.size(); ++i) { + const auto& data = cc_out.dl_cc_result->pdcch_dl[i]; + if (data.dci.ctx.rnti != ctxt.rnti) { + continue; + } + tti_point pdcch_tti = cc_out.tti; + uint32_t k1 = ctxt.ue_cfg.phy_cfg.harq_ack + .dl_data_to_ul_ack[pdcch_tti.sf_idx() % ctxt.ue_cfg.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; + tti_point uci_tti = pdcch_tti + k1; + + ctxt.cc_list[cc_out.cc].pending_acks[uci_tti.to_uint()]++; + } + + // clear up old slots + ctxt.cc_list[cc_out.cc].pending_acks[(cc_out.tti - 1).to_uint()] = 0; + return SRSRAN_SUCCESS; } @@ -54,7 +72,7 @@ void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) // It is newtx h.nof_retxs = 0; h.ndi = data.dci.ndi; - h.first_tti_rx = cc_out.tti_rx; + h.first_tti_tx = cc_out.tti; h.dci_loc = data.dci.ctx.location; h.tbs = 100; // TODO } else { @@ -62,7 +80,11 @@ void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out) h.nof_retxs++; } h.active = true; - h.last_tti_rx = cc_out.tti_rx; + h.last_tti_tx = cc_out.tti; + h.last_tti_ack = + h.last_tti_tx + + ctxt.ue_cfg.phy_cfg.harq_ack + .dl_data_to_ul_ack[h.last_tti_tx.sf_idx() % ctxt.ue_cfg.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; h.nof_txs++; } } @@ -81,6 +103,7 @@ sched_nr_sim_base::sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& cell_params.emplace_back(cc, cell_cfg_list[cc], sched_args); } sched_ptr->cell_cfg(cell_cfg_list); // call parent cfg + TESTASSERT(cell_params.size() > 0); } @@ -94,60 +117,68 @@ int sched_nr_sim_base::add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_ TESTASSERT(ue_db.count(rnti) == 0); sched_ptr->ue_cfg(rnti, ue_cfg_); - ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_rx, preamble_idx))); + ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_tx, preamble_idx))); return SRSRAN_SUCCESS; } -void sched_nr_sim_base::new_slot(srsran::tti_point tti_rx) +void sched_nr_sim_base::new_slot(srsran::tti_point tti_tx) { - { - std::unique_lock lock(mutex); - logger.set_context(tti_rx.to_uint()); - mac_logger.set_context(tti_rx.to_uint()); - current_tti_rx = tti_rx; - logger.info("---------------- TTI=%d ---------------", tti_rx.to_uint()); - for (auto& ue : ue_db) { - ue_tti_events events; - set_default_tti_events(ue.second.get_ctxt(), events); - set_external_tti_events(ue.second.get_ctxt(), events); - apply_tti_events(ue.second.get_ctxt(), events); - } + std::unique_lock lock(mutex); + while (cc_finished > 0) { + cvar.wait(lock); + } + logger.set_context(tti_tx.to_uint()); + mac_logger.set_context(tti_tx.to_uint()); + logger.info("---------------- TTI=%d ---------------", tti_tx.to_uint()); + current_tti_tx = tti_tx; + cc_finished = cell_params.size(); + for (auto& ue : ue_db) { + ue_nr_tti_events events; + set_default_tti_events(ue.second.get_ctxt(), events); + set_external_tti_events(ue.second.get_ctxt(), events); + apply_tti_events(ue.second.get_ctxt(), events); } } void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out) { std::unique_lock lock(mutex); - for (auto& ue_pair : ue_db) { - ue_pair.second.update(cc_out); + + sim_nr_enb_ctxt_t ctxt; + ctxt = get_enb_ctxt(); + test_dl_sched_result(ctxt, cc_out); + + for (auto& u : ue_db) { + u.second.update(cc_out); + } + + if (--cc_finished <= 0) { + cvar.notify_one(); } } -int sched_nr_sim_base::set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) +int sched_nr_sim_base::set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_nr_tti_events& pending_events) { pending_events.cc_list.clear(); pending_events.cc_list.resize(cell_params.size()); - pending_events.tti_rx = current_tti_rx; + pending_events.tti_rx = current_tti_tx; for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_events.cc_list.size(); ++enb_cc_idx) { auto& cc_feedback = pending_events.cc_list[enb_cc_idx]; cc_feedback.configured = true; - cc_feedback.ue_cc_idx = enb_cc_idx; for (uint32_t pid = 0; pid < SCHED_NR_MAX_HARQ; ++pid) { - auto& dl_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[pid]; - auto& ul_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[pid]; + auto& dl_h = ue_ctxt.cc_list[enb_cc_idx].dl_harqs[pid]; + auto& ul_h = ue_ctxt.cc_list[enb_cc_idx].ul_harqs[pid]; // Set default DL ACK - if (dl_h.active and (dl_h.last_tti_rx + 8) == current_tti_rx) { - cc_feedback.dl_pid = pid; - cc_feedback.dl_ack = true; // default is ACK + if (dl_h.active and (dl_h.last_tti_ack) == current_tti_tx) { + cc_feedback.dl_acks.push_back(ue_nr_tti_events::ack_t{pid, true}); } // Set default UL ACK - if (ul_h.active and (ul_h.last_tti_rx + 8) == current_tti_rx) { - cc_feedback.ul_pid = pid; - cc_feedback.ul_ack = true; + if (ul_h.active and (ul_h.last_tti_tx + 8) == current_tti_tx) { + cc_feedback.ul_acks.emplace_back(ue_nr_tti_events::ack_t{pid, true}); } // TODO: other CSI @@ -157,7 +188,7 @@ int sched_nr_sim_base::set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, u return SRSRAN_SUCCESS; } -int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events) +int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_nr_tti_events& events) { for (uint32_t enb_cc_idx = 0; enb_cc_idx < events.cc_list.size(); ++enb_cc_idx) { const auto& cc_feedback = events.cc_list[enb_cc_idx]; @@ -165,35 +196,29 @@ int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_ continue; } - if (cc_feedback.dl_pid >= 0) { - auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; + for (auto& ack : cc_feedback.dl_acks) { + auto& h = ue_ctxt.cc_list[enb_cc_idx].dl_harqs[ack.pid]; - if (cc_feedback.dl_ack) { - logger.info("DL ACK rnti=0x%x tti_dl_tx=%u cc=%d pid=%d", - ue_ctxt.rnti, - to_tx_dl(h.last_tti_rx).to_uint(), - enb_cc_idx, - cc_feedback.dl_pid); + if (ack.ack) { + logger.info( + "DL ACK rnti=0x%x tti_dl_tx=%u cc=%d pid=%d", ue_ctxt.rnti, h.last_tti_tx.to_uint(), enb_cc_idx, ack.pid); } // update scheduler - sched_ptr->dl_ack_info(ue_ctxt.rnti, enb_cc_idx, cc_feedback.dl_pid, cc_feedback.tb, cc_feedback.dl_ack); + sched_ptr->dl_ack_info(ue_ctxt.rnti, enb_cc_idx, h.pid, 0, ack.ack); // update UE sim context - if (cc_feedback.dl_ack or ue_ctxt.is_last_dl_retx(cc_feedback.ue_cc_idx, cc_feedback.dl_pid)) { + if (ack.ack or ue_ctxt.is_last_dl_retx(enb_cc_idx, h.pid)) { h.active = false; } } - if (cc_feedback.ul_pid >= 0) { - auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.ul_pid]; + for (auto& ack : cc_feedback.ul_acks) { + auto& h = ue_ctxt.cc_list[enb_cc_idx].ul_harqs[ack.pid]; - if (cc_feedback.ul_ack) { - logger.info("UL ACK rnti=0x%x, tti_ul_tx=%u, cc=%d pid=%d", - ue_ctxt.rnti, - to_tx_ul(h.last_tti_rx).to_uint(), - enb_cc_idx, - cc_feedback.ul_pid); + if (ack.ack) { + logger.info( + "UL ACK rnti=0x%x, tti_ul_tx=%u, cc=%d pid=%d", ue_ctxt.rnti, h.last_tti_tx.to_uint(), enb_cc_idx, h.pid); } // // update scheduler @@ -207,4 +232,16 @@ int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_ return SRSRAN_SUCCESS; } +sim_nr_enb_ctxt_t sched_nr_sim_base::get_enb_ctxt() const +{ + sim_nr_enb_ctxt_t ctxt; + ctxt.cell_params = cell_params; + + for (auto& ue_pair : ue_db) { + ctxt.ue_db.insert(std::make_pair(ue_pair.first, &ue_pair.second.get_ctxt())); + } + + return ctxt; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsenb/test/mac/nr/sched_nr_sim_ue.h index ccac6f2d0..6c78a9188 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.h +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.h @@ -15,20 +15,49 @@ #include "../sched_sim_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsran/adt/circular_array.h" #include namespace srsenb { +const static uint32_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS; + +struct ue_nr_harq_ctxt_t { + bool active = false; + bool ndi = false; + uint32_t pid = 0; + uint32_t nof_txs = 0; + uint32_t nof_retxs = std::numeric_limits::max(); + uint32_t riv = 0; + srsran_dci_location_t dci_loc = {}; + uint32_t tbs = 0; + tti_point last_tti_tx, first_tti_tx, last_tti_ack; +}; struct sched_nr_cc_output_res_t { - tti_point tti_rx; - uint32_t cc; - sched_nr_interface::dl_sched_t* dl_cc_result; - sched_nr_interface::ul_sched_t* ul_cc_result; + tti_point tti; + uint32_t cc; + const sched_nr_interface::dl_sched_t* dl_cc_result; + const sched_nr_interface::ul_sched_t* ul_cc_result; }; struct ue_nr_cc_ctxt_t { - std::array dl_harqs; - std::array ul_harqs; + std::array dl_harqs; + std::array ul_harqs; + srsran::circular_array pending_acks; +}; + +struct ue_nr_tti_events { + struct ack_t { + uint32_t pid; + bool ack; + }; + struct cc_data { + bool configured = false; + srsran::bounded_vector dl_acks; + srsran::bounded_vector ul_acks; + }; + srsran::tti_point tti_rx; + std::vector cc_list; }; struct sim_nr_ue_ctxt_t { @@ -44,6 +73,10 @@ struct sim_nr_ue_ctxt_t { return h.nof_retxs + 1 >= ue_cfg.maxharq_tx; } }; +struct sim_nr_enb_ctxt_t { + srsran::span cell_params; + std::map ue_db; +}; class sched_nr_ue_sim { @@ -75,7 +108,7 @@ public: int add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx); - void new_slot(srsran::tti_point tti_rx); + void new_slot(srsran::tti_point tti_tx); void update(sched_nr_cc_output_res_t& cc_out); sched_nr_ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); } @@ -101,18 +134,20 @@ public: tti_point get_tti_rx() const { std::lock_guard lock(mutex); - return current_tti_rx; + return current_tti_tx; } + sim_nr_enb_ctxt_t get_enb_ctxt() const; + std::map::iterator begin() { return ue_db.begin(); } std::map::iterator end() { return ue_db.end(); } // configurable by simulator concrete implementation - virtual void set_external_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) {} + virtual void set_external_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_nr_tti_events& pending_events) {} private: - int set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events); - int apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events); + int set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_nr_tti_events& pending_events); + int apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_nr_tti_events& events); std::string test_name; srslog::basic_logger& logger; @@ -120,11 +155,13 @@ private: std::unique_ptr sched_ptr; std::vector cell_params; - srsran::tti_point current_tti_rx; + srsran::tti_point current_tti_tx; + int cc_finished = 0; + std::map ue_db; mutable std::mutex mutex; - std::condition_variable cond_var; + std::condition_variable cvar; }; } // namespace srsenb diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index c3d058131..8d9f18b06 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -154,7 +154,7 @@ void sched_nr_cfg_serialized_test() sched_tester.add_user(0x46, uecfg, 0); - auto tp1 = std::chrono::steady_clock::now(); + std::vector count_per_cc(nof_sectors, 0); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; @@ -163,26 +163,32 @@ void sched_nr_cfg_serialized_test() for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { sched_nr_interface::dl_sched_t dl_res; sched_nr_interface::ul_sched_t ul_res; + auto tp1 = std::chrono::steady_clock::now(); TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); + auto tp2 = std::chrono::steady_clock::now(); + count_per_cc[cc] += std::chrono::duration_cast(tp2 - tp1).count(); sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(tti_rx, dl_res, ul_res); TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti_tx).sf_idx()) or dl_res.pdcch_dl.size() == 1); } } - auto tp2 = std::chrono::steady_clock::now(); tasks.print_results(); TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); - uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); - printf("Total time taken per slot: %f\n", microsecs / (float)max_nof_ttis); + double final_avg_usec = 0; + for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + final_avg_usec += count_per_cc[cc]; + } + final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis; + printf("Total time taken per slot: %f usec\n", final_avg_usec); } void sched_nr_cfg_parallel_cc_test() { - uint32_t nof_sectors = 4; + uint32_t nof_sectors = 2; uint32_t max_nof_ttis = 1000; task_job_manager tasks; @@ -194,33 +200,40 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched_tester.add_user(0x46, uecfg, 0); - auto tp1 = std::chrono::steady_clock::now(); + std::vector > nano_count(nof_sectors); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; tasks.start_slot(tti_tx, nof_sectors); sched_tester.new_slot(tti_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - srsran::get_background_workers().push_task([cc, tti_tx, &tasks, &sched_tester]() { + srsran::get_background_workers().push_task([cc, tti_tx, &tasks, &sched_tester, &nano_count]() { sched_nr_interface::dl_sched_t dl_res; sched_nr_interface::ul_sched_t ul_res; + auto tp1 = std::chrono::steady_clock::now(); TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); + auto tp2 = std::chrono::steady_clock::now(); + nano_count[cc].fetch_add(std::chrono::duration_cast(tp2 - tp1).count(), + std::memory_order_relaxed); sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(tti_tx, dl_res, ul_res); }); } } - auto tp2 = std::chrono::steady_clock::now(); tasks.wait_task_finish(); tasks.print_results(); TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); - uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); - printf("Total time taken per slot [usec]: %f\n", microsecs / (float)max_nof_ttis); + double final_avg_usec = 0; + for (uint32_t i = 0; i < nano_count.size(); ++i) { + final_avg_usec += nano_count[i]; + } + final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis / nof_sectors; + printf("Total time taken per slot [usec]: %f\n", final_avg_usec); } void sched_nr_cfg_parallel_sf_test() @@ -233,34 +246,44 @@ void sched_nr_cfg_parallel_sf_test() cfg.nof_concurrent_subframes = 2; std::vector cells_cfg = get_default_cells_cfg(nof_sectors); - sched_nr sched(cfg); - sched.cell_cfg(cells_cfg); + sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel SF Test"); sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); - sched.ue_cfg(0x46, uecfg); + sched_tester.add_user(0x46, uecfg, 0); - auto tp1 = std::chrono::steady_clock::now(); + std::vector > nano_count(nof_sectors); for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { - tti_point tti(nof_ttis % 10240); - tasks.start_slot(tti, nof_sectors); + tti_point tti_rx(nof_ttis % 10240); + tti_point tti_tx = tti_rx + TX_ENB_DELAY; + tasks.start_slot(tti_tx, nof_sectors); + sched_tester.new_slot(tti_tx); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { - srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { + srsran::get_background_workers().push_task([cc, tti_tx, &sched_tester, &tasks, &nano_count]() { sched_nr_interface::dl_sched_t dl_res; sched_nr_interface::ul_sched_t ul_res; - TESTASSERT(sched.get_dl_sched(tti, cc, dl_res) == SRSRAN_SUCCESS); - TESTASSERT(sched.get_ul_sched(tti, cc, ul_res) == SRSRAN_SUCCESS); - tasks.finish_cc(tti, dl_res, ul_res); + auto tp1 = std::chrono::steady_clock::now(); + TESTASSERT(sched_tester.get_sched()->get_dl_sched(tti_tx, cc, dl_res) == SRSRAN_SUCCESS); + TESTASSERT(sched_tester.get_sched()->get_ul_sched(tti_tx, cc, ul_res) == SRSRAN_SUCCESS); + auto tp2 = std::chrono::steady_clock::now(); + nano_count[cc].fetch_add(std::chrono::duration_cast(tp2 - tp1).count(), + std::memory_order_relaxed); + sched_nr_cc_output_res_t out{tti_tx, cc, &dl_res, &ul_res}; + sched_tester.update(out); + tasks.finish_cc(tti_tx, dl_res, ul_res); }); } } - auto tp2 = std::chrono::steady_clock::now(); tasks.wait_task_finish(); tasks.print_results(); - uint32_t microsecs = std::chrono::duration_cast(tp2 - tp1).count(); - printf("Total time taken per slot [usec]: %f\n", microsecs / (float)max_nof_ttis); + double final_avg_usec = 0; + for (uint32_t i = 0; i < nano_count.size(); ++i) { + final_avg_usec += nano_count[i]; + } + final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis / nof_sectors; + printf("Total time taken per slot [usec]: %f\n", final_avg_usec); } } // namespace srsenb @@ -268,16 +291,16 @@ void sched_nr_cfg_parallel_sf_test() int main() { auto& test_logger = srslog::fetch_basic_logger("TEST"); - test_logger.set_level(srslog::basic_levels::debug); + test_logger.set_level(srslog::basic_levels::info); auto& mac_logger = srslog::fetch_basic_logger("MAC"); - mac_logger.set_level(srslog::basic_levels::debug); + mac_logger.set_level(srslog::basic_levels::info); auto& pool_logger = srslog::fetch_basic_logger("POOL"); - pool_logger.set_level(srslog::basic_levels::debug); + pool_logger.set_level(srslog::basic_levels::info); // Start the log backend. srslog::init(); - srsran::get_background_workers().set_nof_workers(8); + srsran::get_background_workers().set_nof_workers(6); srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc new file mode 100644 index 000000000..05e8da412 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc @@ -0,0 +1,54 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "sched_nr_ue_ded_test_suite.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsran/common/test_common.h" + +namespace srsenb { + +using namespace srsenb::sched_nr_impl; + +void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_output_res_t& cc_out) +{ + tti_point pdcch_tti = cc_out.tti; + const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl; + + // Iterate over UE PDCCH allocations + for (const pdcch_dl_t& pdcch : pdcchs) { + if (pdcch.dci.ctx.rnti_type != srsran_rnti_type_c) { + continue; + } + const sim_nr_ue_ctxt_t& ue = *enb_ctxt.ue_db.at(pdcch.dci.ctx.rnti); + uint32_t k1 = ue.ue_cfg.phy_cfg.harq_ack + .dl_data_to_ul_ack[pdcch_tti.sf_idx() % ue.ue_cfg.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; + + // CHECK: Carrier activation + TESTASSERT(ue.ue_cfg.carriers[cc_out.cc].active); + + // CHECK: Coreset chosen/DCI content + TESTASSERT(ue.ue_cfg.phy_cfg.pdcch.coreset_present[pdcch.dci.ctx.coreset_id]); + const auto& coreset = ue.ue_cfg.phy_cfg.pdcch.coreset[pdcch.dci.ctx.coreset_id]; + TESTASSERT(coreset.id == pdcch.dci.ctx.coreset_id); + TESTASSERT(pdcch.dci.ctx.format == srsran_dci_format_nr_1_0 or pdcch.dci.ctx.format == srsran_dci_format_nr_1_1); + + // CHECK: UCI + if (pdcch.dci.ctx.format == srsran_dci_format_nr_1_0) { + TESTASSERT(pdcch.dci.harq_feedback == k1 - 1); + } else { + TESTASSERT(pdcch.dci.harq_feedback == pdcch_tti.sf_idx()); + } + TESTASSERT(ue.cc_list[cc_out.cc].pending_acks[(pdcch_tti + k1).to_uint()] % 4 == pdcch.dci.dai); + } +} + +} // namespace srsenb diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h new file mode 100644 index 000000000..3bc19f74f --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h @@ -0,0 +1,24 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_UE_DED_TEST_SUITE_H +#define SRSRAN_SCHED_NR_UE_DED_TEST_SUITE_H + +#include "sched_nr_sim_ue.h" + +namespace srsenb { + +void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_output_res_t& cc_out); + +} + +#endif // SRSRAN_SCHED_NR_UE_DED_TEST_SUITE_H From d9336bcd9eb355fe57c58b4a4e8d301044fb19c7 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 14 Jul 2021 15:47:01 +0100 Subject: [PATCH 57/59] sched,nr: creation of pool of softbuffers for NR. Now the sched NR harq manages the lifetime of the softbuffer and its forwarding to the PHY --- .../srsran/interfaces/gnb_interfaces.h | 5 +- srsenb/hdr/stack/mac/nr/harq_softbuffer.h | 132 ++++++++++++++++++ srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 2 + srsenb/hdr/stack/mac/nr/sched_nr_harq.h | 49 +++++-- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 3 +- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 2 +- srsenb/src/stack/mac/nr/CMakeLists.txt | 2 +- srsenb/src/stack/mac/nr/harq_softbuffer.cc | 62 ++++++++ srsenb/src/stack/mac/nr/sched_nr.cc | 2 + srsenb/src/stack/mac/nr/sched_nr_bwp.cc | 5 + srsenb/src/stack/mac/nr/sched_nr_harq.cc | 7 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 1 + srsenb/src/stack/mac/nr/sched_nr_ue.cc | 6 +- .../test/mac/nr/sched_nr_ue_ded_test_suite.cc | 8 +- 14 files changed, 268 insertions(+), 18 deletions(-) create mode 100644 srsenb/hdr/stack/mac/nr/harq_softbuffer.h create mode 100644 srsenb/src/stack/mac/nr/harq_softbuffer.cc diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 71b5d424d..56d6fd47b 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -214,8 +214,9 @@ public: }; struct pdsch_t { - srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration - std::array data = {}; ///< Data pointer + srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration + std::array data = {}; ///< Data pointer + std::array tx_softbuffer = {}; ///< HARQ-specific Softbuffer }; struct ssb_t { diff --git a/srsenb/hdr/stack/mac/nr/harq_softbuffer.h b/srsenb/hdr/stack/mac/nr/harq_softbuffer.h new file mode 100644 index 000000000..ec33718b6 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/harq_softbuffer.h @@ -0,0 +1,132 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_HARQ_SOFTBUFFER_H +#define SRSRAN_HARQ_SOFTBUFFER_H + +#include "srsran/adt/pool/pool_interface.h" +#include "srsran/adt/span.h" +extern "C" { +#include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/fec/softbuffer.h" +} + +namespace srsenb { + +class tx_harq_softbuffer +{ +public: + tx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); } + explicit tx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_tx_init(&buffer, nof_prb_); } + tx_harq_softbuffer(const tx_harq_softbuffer&) = delete; + tx_harq_softbuffer(tx_harq_softbuffer&& other) noexcept + { + memcpy(&buffer, &other.buffer, sizeof(other.buffer)); + bzero(&other.buffer, sizeof(other.buffer)); + } + tx_harq_softbuffer& operator=(const tx_harq_softbuffer&) = delete; + tx_harq_softbuffer& operator =(tx_harq_softbuffer&& other) noexcept + { + if (this != &other) { + destroy(); + memcpy(&buffer, &other.buffer, sizeof(other.buffer)); + bzero(&other.buffer, sizeof(other.buffer)); + } + return *this; + } + ~tx_harq_softbuffer() { destroy(); } + + void reset() { srsran_softbuffer_tx_reset(&buffer); } + + srsran_softbuffer_tx_t& operator*() { return buffer; } + const srsran_softbuffer_tx_t& operator*() const { return buffer; } + srsran_softbuffer_tx_t* operator->() { return &buffer; } + const srsran_softbuffer_tx_t* operator->() const { return &buffer; } + srsran_softbuffer_tx_t* get() { return &buffer; } + const srsran_softbuffer_tx_t* get() const { return &buffer; } + +private: + void destroy() { srsran_softbuffer_tx_free(&buffer); } + + srsran_softbuffer_tx_t buffer; +}; + +class rx_harq_softbuffer +{ +public: + rx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); } + explicit rx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_rx_init(&buffer, nof_prb_); } + rx_harq_softbuffer(const rx_harq_softbuffer&) = delete; + rx_harq_softbuffer(rx_harq_softbuffer&& other) noexcept + { + memcpy(&buffer, &other.buffer, sizeof(other.buffer)); + bzero(&other.buffer, sizeof(other.buffer)); + } + rx_harq_softbuffer& operator=(const rx_harq_softbuffer&) = delete; + rx_harq_softbuffer& operator =(rx_harq_softbuffer&& other) noexcept + { + if (this != &other) { + destroy(); + memcpy(&buffer, &other.buffer, sizeof(other.buffer)); + bzero(&other.buffer, sizeof(other.buffer)); + } + return *this; + } + ~rx_harq_softbuffer() { destroy(); } + + void reset() { srsran_softbuffer_rx_reset(&buffer); } + void reset(uint32_t tbs_bits) { srsran_softbuffer_rx_reset_tbs(&buffer, tbs_bits); } + + srsran_softbuffer_rx_t& operator*() { return buffer; } + const srsran_softbuffer_rx_t& operator*() const { return buffer; } + srsran_softbuffer_rx_t* operator->() { return &buffer; } + const srsran_softbuffer_rx_t* operator->() const { return &buffer; } + srsran_softbuffer_rx_t* get() { return &buffer; } + const srsran_softbuffer_rx_t* get() const { return &buffer; } + +private: + void destroy() { srsran_softbuffer_rx_free(&buffer); } + + srsran_softbuffer_rx_t buffer; +}; + +class harq_softbuffer_pool +{ +public: + harq_softbuffer_pool(const harq_softbuffer_pool&) = delete; + harq_softbuffer_pool(harq_softbuffer_pool&&) = delete; + harq_softbuffer_pool& operator=(const harq_softbuffer_pool&) = delete; + harq_softbuffer_pool& operator=(harq_softbuffer_pool&&) = delete; + + void init_pool(uint32_t nof_prb, uint32_t batch_size = MAX_HARQ * 4, uint32_t thres = 0, uint32_t init_size = 0); + + srsran::unique_pool_ptr get_tx(uint32_t nof_prb); + srsran::unique_pool_ptr get_rx(uint32_t nof_prb); + + static harq_softbuffer_pool& get_instance() + { + static harq_softbuffer_pool pool; + return pool; + } + +private: + const static uint32_t MAX_HARQ = 16; + + harq_softbuffer_pool() = default; + + std::array >, SRSRAN_MAX_PRB_NR> tx_pool; + std::array >, SRSRAN_MAX_PRB_NR> rx_pool; +}; + +} // namespace srsenb + +#endif // SRSRAN_HARQ_SOFTBUFFER_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 1f3b7097a..043df2914 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -57,6 +57,8 @@ struct sched_cell_params { std::vector bwps; sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_); + + uint32_t nof_prb() const { return cell_cfg.carrier.nof_prb; } }; struct sched_params { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h index 90644e602..6371f322d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_harq.h @@ -14,6 +14,7 @@ #define SRSRAN_SCHED_NR_HARQ_H #include "sched_nr_cfg.h" +#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" #include "srsran/common/tti_point.h" #include @@ -70,23 +71,55 @@ private: std::array tb; }; +class dl_harq_proc : public harq_proc +{ +public: + dl_harq_proc(uint32_t id_, uint32_t nprb) : + harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_tx(nprb)) + {} + + tx_harq_softbuffer& get_softbuffer() { return *softbuffer; } + +private: + srsran::unique_pool_ptr softbuffer; +}; + +class ul_harq_proc : public harq_proc +{ +public: + ul_harq_proc(uint32_t id_, uint32_t nprb) : + harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_rx(nprb)) + {} + + rx_harq_softbuffer& get_softbuffer() { return *softbuffer; } + + bool set_tbs(uint32_t tbs) + { + softbuffer->reset(tbs * 8u); + return harq_proc::set_tbs(tbs); + } + +private: + srsran::unique_pool_ptr softbuffer; +}; + class harq_entity { public: - explicit harq_entity(uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ); + explicit harq_entity(uint32_t nprb, uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ); void new_tti(tti_point tti_rx_); void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } - harq_proc* find_pending_dl_retx() + dl_harq_proc* find_pending_dl_retx() { - return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); + return find_dl([this](const dl_harq_proc& h) { return h.has_pending_retx(tti_rx); }); } harq_proc* find_pending_ul_retx() { return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); } - harq_proc* find_empty_dl_harq() + dl_harq_proc* find_empty_dl_harq() { return find_dl([](const harq_proc& h) { return h.empty(); }); } @@ -97,7 +130,7 @@ public: private: template - harq_proc* find_dl(Predicate p) + dl_harq_proc* find_dl(Predicate p) { auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p); return (it == dl_harqs.end()) ? nullptr : &(*it); @@ -109,9 +142,9 @@ private: return (it == ul_harqs.end()) ? nullptr : &(*it); } - tti_point tti_rx; - std::vector dl_harqs; - std::vector ul_harqs; + tti_point tti_rx; + std::vector dl_harqs; + std::vector ul_harqs; }; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index b934d7b6c..bf68f3684 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -68,7 +68,8 @@ public: }; struct ue_cc_cfg_t { - bool active = false; + bool active = false; + uint32_t cc = 0; }; struct ue_cfg_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index fa95640fc..d7fc633dc 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -53,7 +53,7 @@ public: tti_point uci_tti; uint32_t dl_cqi; uint32_t ul_cqi; - harq_proc* h_dl = nullptr; + dl_harq_proc* h_dl = nullptr; harq_proc* h_ul = nullptr; private: diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index df28c36a2..b71ffe52a 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -7,6 +7,6 @@ # set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc - sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc) + sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc harq_softbuffer.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/harq_softbuffer.cc b/srsenb/src/stack/mac/nr/harq_softbuffer.cc new file mode 100644 index 000000000..b60465d8f --- /dev/null +++ b/srsenb/src/stack/mac/nr/harq_softbuffer.cc @@ -0,0 +1,62 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" +#include "srsran/adt/pool/obj_pool.h" + +namespace srsenb { + +void harq_softbuffer_pool::init_pool(uint32_t nof_prb, uint32_t batch_size, uint32_t thres, uint32_t init_size) +{ + srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid nof prb=%d", nof_prb); + size_t idx = nof_prb - 1; + if (tx_pool[idx] != nullptr) { + return; + } + if (thres == 0) { + thres = batch_size; + } + if (init_size == 0) { + init_size = batch_size; + } + auto init_tx_softbuffers = [nof_prb](void* ptr) { new (ptr) tx_harq_softbuffer(nof_prb); }; + auto recycle_tx_softbuffers = [](tx_harq_softbuffer& softbuffer) { softbuffer.reset(); }; + tx_pool[idx].reset(new srsran::background_obj_pool( + batch_size, thres, init_size, init_tx_softbuffers, recycle_tx_softbuffers)); + + auto init_rx_softbuffers = [nof_prb](void* ptr) { new (ptr) rx_harq_softbuffer(nof_prb); }; + auto recycle_rx_softbuffers = [](rx_harq_softbuffer& softbuffer) { softbuffer.reset(); }; + rx_pool[idx].reset(new srsran::background_obj_pool( + batch_size, thres, init_size, init_rx_softbuffers, recycle_rx_softbuffers)); +} + +srsran::unique_pool_ptr harq_softbuffer_pool::get_tx(uint32_t nof_prb) +{ + srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb); + size_t idx = nof_prb - 1; + if (tx_pool[idx] == nullptr) { + init_pool(nof_prb); + } + return tx_pool[idx]->make(); +} + +srsran::unique_pool_ptr harq_softbuffer_pool::get_rx(uint32_t nof_prb) +{ + srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb); + size_t idx = nof_prb - 1; + if (rx_pool[idx] == nullptr) { + init_pool(nof_prb); + } + return rx_pool[idx]->make(); +} + +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 90caf0ca1..0b6ed58e7 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsran/common/thread_pool.h" @@ -156,6 +157,7 @@ int sched_nr::cell_cfg(srsran::const_span cell_list) pending_results.reset(new sched_result_manager(cell_list.size())); sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg)); + return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc index 1e9a4b38f..03f7c314b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -145,11 +145,16 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg) {} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) { for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { bwps.emplace_back(cell_cfg_.bwps[bwp_id]); } + + // Pre-allocate HARQs in common pool of softbuffers + harq_softbuffer_pool::get_instance().init_pool(cfg->nof_prb()); } } // namespace sched_nr_impl diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsenb/src/stack/mac/nr/sched_nr_harq.cc index 4bc674d07..928523347 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_harq.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_harq.cc @@ -100,13 +100,14 @@ bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_) return true; } -harq_entity::harq_entity(uint32_t nof_harq_procs) +harq_entity::harq_entity(uint32_t nprb, uint32_t nof_harq_procs) { + // Create HARQs dl_harqs.reserve(nof_harq_procs); ul_harqs.reserve(nof_harq_procs); for (uint32_t pid = 0; pid < nof_harq_procs; ++pid) { - dl_harqs.emplace_back(pid); - ul_harqs.emplace_back(pid); + dl_harqs.emplace_back(pid, nprb); + ul_harqs.emplace_back(pid, nprb); } } diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index c4e7b0567..89df24dcc 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -191,6 +191,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr } else { srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx"); } + pdsch.tx_softbuffer[0] = *ue.h_dl->get_softbuffer(); return alloc_result::success; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index bd022efb9..3daa087f0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -23,7 +23,11 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) : - rnti(rnti_), cc(cell_params_.cc), bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_), cell_params(cell_params_) + rnti(rnti_), + cc(cell_params_.cc), + bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_), + cell_params(cell_params_), + harq_ent(cell_params_.nof_prb()) {} void ue_carrier::push_feedback(srsran::move_callback callback) diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc index 05e8da412..aac2d2629 100644 --- a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc @@ -11,7 +11,7 @@ */ #include "sched_nr_ue_ded_test_suite.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" #include "srsran/common/test_common.h" namespace srsenb { @@ -22,6 +22,7 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o { tti_point pdcch_tti = cc_out.tti; const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl; + const pdsch_list_t& pdschs = cc_out.dl_cc_result->pdsch; // Iterate over UE PDCCH allocations for (const pdcch_dl_t& pdcch : pdcchs) { @@ -49,6 +50,11 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o } TESTASSERT(ue.cc_list[cc_out.cc].pending_acks[(pdcch_tti + k1).to_uint()] % 4 == pdcch.dci.dai); } + + for (const pdsch_t& pdsch : pdschs) { + TESTASSERT(pdsch.tx_softbuffer[0].buffer_b != nullptr); + TESTASSERT(pdsch.tx_softbuffer[0].max_cb > 0); + } } } // namespace srsenb From 8a34a3c41aceeb67bc23617f918669cbbed05144 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 14 Jul 2021 17:01:02 +0100 Subject: [PATCH 58/59] sched,nr: fix compilation issues in centos7 and removed unused variables --- srsenb/hdr/stack/mac/nr/sched_nr_cfg.h | 3 ++- srsenb/hdr/stack/mac/nr/sched_nr_ue.h | 1 - srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 4 ++++ srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 5 +++++ srsenb/test/mac/nr/sched_nr_test.cc | 8 ++++---- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 043df2914..8ec8bfe37 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -95,6 +95,7 @@ public: const ue_cfg_t* ue_cfg() const { return cfg_; } const srsran::phy_cfg_nr_t& phy() const { return cfg_->phy_cfg; } + const bwp_params& active_bwp() const { return *bwp_cfg; } const bwp_cce_pos_list& cce_pos_list(uint32_t search_id) const { return cce_positions_list[ss_id_to_cce_idx[search_id]]; @@ -102,8 +103,8 @@ public: private: uint16_t rnti = SRSRAN_INVALID_RNTI; - const bwp_params* bwp_cfg = nullptr; const ue_cfg_t* cfg_ = nullptr; + const bwp_params* bwp_cfg = nullptr; std::vector cce_positions_list; std::array ss_id_to_cce_idx; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index d7fc633dc..97ece0a45 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -46,7 +46,6 @@ public: // UE parameters that are sector specific const ue_cc_cfg_t* cc_cfg = nullptr; - uint32_t bwp_id; tti_point pdcch_tti; tti_point pdsch_tti; tti_point pusch_tti; diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index e9b44bf7f..cc9469fa7 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -30,7 +30,7 @@ void fill_dci_common(const slot_ue& ue, const bwp_params& bwp_cfg, DciDlOrUl& dc { const static uint32_t rv_idx[4] = {0, 2, 3, 1}; - dci.bwp_id = ue.bwp_id; + dci.bwp_id = ue.cfg->active_bwp().bwp_id; dci.cc_id = ue.cc; dci.tpc = 1; // harq diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 87371aed4..2c59d6257 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -32,6 +32,10 @@ coreset_region::coreset_region(const bwp_params& bwp_cfg_, nof_freq_res = std::count(res_active, res_active + SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, true); srsran_assert(get_td_symbols() <= SRSRAN_CORESET_DURATION_MAX, "Possible number of time-domain OFDM symbols in CORESET must be within {1,2,3}"); + srsran_assert(nof_freq_res <= bwp_cfg_.cell_cfg.carrier.nof_prb, + "The number of frequency resources=%d of coreset_id=%d exceeds BWP bandwidth", + nof_freq_res, + coreset_id); } void coreset_region::reset() diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 89df24dcc..65d90064d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -119,6 +119,11 @@ alloc_result bwp_slot_allocator::alloc_rar(uint32_t alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant) { + if (ue.cfg->active_bwp().bwp_id != bwp_grid.cfg->bwp_id) { + logger.warning( + "SCHED: Trying to allocate PDSCH for rnti=0x%x in inactive BWP id=%d", ue.rnti, ue.cfg->active_bwp().bwp_id); + return alloc_result::no_rnti_opportunity; + } if (ue.h_dl == nullptr) { logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); return alloc_result::no_rnti_opportunity; diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 8d9f18b06..39fb16437 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -200,7 +200,7 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched_tester.add_user(0x46, uecfg, 0); - std::vector > nano_count(nof_sectors); + std::array, SRSRAN_MAX_CARRIERS> nano_count{}; for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; @@ -229,7 +229,7 @@ void sched_nr_cfg_parallel_cc_test() TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6)); double final_avg_usec = 0; - for (uint32_t i = 0; i < nano_count.size(); ++i) { + for (uint32_t i = 0; i < nof_sectors; ++i) { final_avg_usec += nano_count[i]; } final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis / nof_sectors; @@ -251,7 +251,7 @@ void sched_nr_cfg_parallel_sf_test() sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); sched_tester.add_user(0x46, uecfg, 0); - std::vector > nano_count(nof_sectors); + std::array, SRSRAN_MAX_CARRIERS> nano_count{}; for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti_rx(nof_ttis % 10240); tti_point tti_tx = tti_rx + TX_ENB_DELAY; @@ -279,7 +279,7 @@ void sched_nr_cfg_parallel_sf_test() tasks.print_results(); double final_avg_usec = 0; - for (uint32_t i = 0; i < nano_count.size(); ++i) { + for (uint32_t i = 0; i < nof_sectors; ++i) { final_avg_usec += nano_count[i]; } final_avg_usec = final_avg_usec / 1000.0 / max_nof_ttis / nof_sectors; From 09c7000201b8ce70dbaf13bb0a59c5ae4f4b87e5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 14 Jul 2021 22:29:06 +0100 Subject: [PATCH 59/59] sched,nr: update nr scheduler to use new mac nr interface types --- .../srsran/interfaces/gnb_interfaces.h | 5 ++-- srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h | 1 - srsenb/hdr/stack/mac/nr/sched_nr_rb.h | 1 - srsenb/src/stack/mac/nr/sched_nr_pdcch.cc | 1 - srsenb/src/stack/mac/nr/sched_nr_rb.cc | 1 - srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 24 ++++++++++++++----- .../test/mac/nr/sched_nr_ue_ded_test_suite.cc | 5 ++-- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 56d6fd47b..71b5d424d 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -214,9 +214,8 @@ public: }; struct pdsch_t { - srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration - std::array data = {}; ///< Data pointer - std::array tx_softbuffer = {}; ///< HARQ-specific Softbuffer + srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration + std::array data = {}; ///< Data pointer }; struct ssb_t { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index a846feef7..30cdde0d2 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -62,7 +62,6 @@ public: size_t nof_allocs() const { return dfs_tree.size(); } private: - const bwp_params* bwp_cfg; const srsran_coreset_t* coreset_cfg; uint32_t coreset_id; uint32_t slot_idx; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h index 9fda7eacd..a8e88e2b0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb.h @@ -191,7 +191,6 @@ public: private: prb_bitmap prbs_; rbg_bitmap rbgs_; - uint32_t bwp_prb_start = 0; uint32_t P_ = 0; uint32_t Pnofbits = 0; uint32_t first_rbg_size = 0; diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc index 2c59d6257..4702965bc 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc @@ -21,7 +21,6 @@ coreset_region::coreset_region(const bwp_params& bwp_cfg_, uint32_t slot_idx_, pdcch_dl_list_t& dl_list_, pdcch_ul_list_t& ul_list_) : - bwp_cfg(&bwp_cfg_), coreset_cfg(&bwp_cfg_.cfg.pdcch.coreset[coreset_id_]), coreset_id(coreset_id_), slot_idx(slot_idx_), diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb.cc b/srsenb/src/stack/mac/nr/sched_nr_rb.cc index d03af3592..e24844b7f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb.cc @@ -55,7 +55,6 @@ uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_ bwp_rb_bitmap::bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2) : prbs_(bwp_nof_prbs), rbgs_(get_nof_rbgs(bwp_nof_prbs, bwp_prb_start_, config1_or_2)), - bwp_prb_start(bwp_prb_start_), P_(get_P(bwp_nof_prbs, config1_or_2)), Pnofbits(log2(P_)), first_rbg_size(get_rbg_size(bwp_nof_prbs, bwp_prb_start_, config1_or_2, 0)) diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index 65d90064d..edee6804b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -196,7 +196,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr } else { srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx"); } - pdsch.tx_softbuffer[0] = *ue.h_dl->get_softbuffer(); + pdsch.sch.grant.tb[0].softbuffer.tx = ue.h_dl->get_softbuffer().get(); return alloc_result::success; } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index b50517c73..80ba1ed46 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -232,7 +232,7 @@ bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, d dl_res.pdsch = bwp_slot.pdschs; ul_res.pusch = bwp_slot.puschs; - // Generate PUCCH + // Group pending HARQ ACKs srsran_pdsch_ack_nr_t ack = {}; ack.nof_cc = not bwp_slot.pending_acks.empty(); const srsran::phy_cfg_nr_t* phy_cfg = nullptr; @@ -246,11 +246,23 @@ bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, d if (phy_cfg != nullptr) { srsran_slot_cfg_t slot_cfg{}; - slot_cfg.idx = pdcch_tti.sf_idx(); - ul_res.pucch.emplace_back(); - pucch_t& pucch = ul_res.pucch.back(); - if (not phy_cfg->get_pucch(slot_cfg, ack, pucch.pucch_cfg, pucch.uci_cfg, pucch.resource)) { - logger.error("Error getting UCI CFG"); + slot_cfg.idx = pdcch_tti.sf_idx(); + srsran_uci_cfg_nr_t uci_cfg = {}; + srsran_assert(phy_cfg->get_uci_cfg(slot_cfg, ack, uci_cfg), "Error getting UCI CFG"); + + if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { + if (not ul_res.pusch.empty()) { + // Put UCI configuration in PUSCH config + srsran_assert(phy_cfg->get_pusch_uci_cfg(slot_cfg, uci_cfg, ul_res.pusch[0].sch), + "Error setting UCI configuration in PUSCH"); + } else { + // Put UCI configuration in PUCCH config + ul_res.pucch.emplace_back(); + pucch_t& pucch = ul_res.pucch.back(); + pucch.uci_cfg = uci_cfg; + srsran_assert(phy_cfg->get_pucch_uci_cfg(slot_cfg, pucch.uci_cfg, pucch.pucch_cfg, pucch.resource), + "Error getting PUCCH UCI cfg"); + } } } diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc index aac2d2629..13eba2fb7 100644 --- a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc +++ b/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc @@ -52,8 +52,9 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o } for (const pdsch_t& pdsch : pdschs) { - TESTASSERT(pdsch.tx_softbuffer[0].buffer_b != nullptr); - TESTASSERT(pdsch.tx_softbuffer[0].max_cb > 0); + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx != nullptr); + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->buffer_b != nullptr); + TESTASSERT(pdsch.sch.grant.tb[0].softbuffer.tx->max_cb > 0); } }