From d3c51fdad442cdbc1bf87b6aba9510d46ef1e310 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 30 Apr 2021 14:08:27 +0100 Subject: [PATCH] limit minimum UL grant size to accommodate both BSR and RLC headers --- srsenb/hdr/stack/mac/sched_ue.h | 12 ++- srsenb/src/stack/mac/sched_grid.cc | 6 +- srsenb/src/stack/mac/sched_ue.cc | 5 ++ .../stack/mac/sched_ue_ctrl/sched_ue_cell.cc | 12 ++- srsenb/test/mac/CMakeLists.txt | 4 + srsenb/test/mac/sched_ue_cell_test.cc | 75 +++++++++++++++++++ 6 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 srsenb/test/mac/sched_ue_cell_test.cc diff --git a/srsenb/hdr/stack/mac/sched_ue.h b/srsenb/hdr/stack/mac/sched_ue.h index 3297a1c98..72d985fa0 100644 --- a/srsenb/hdr/stack/mac/sched_ue.h +++ b/srsenb/hdr/stack/mac/sched_ue.h @@ -81,10 +81,12 @@ public: uint32_t get_required_prb_ul(uint32_t enb_cc_idx, uint32_t req_bytes); - rbg_interval get_required_dl_rbgs(uint32_t enb_cc_idx); - srsran::interval get_requested_dl_bytes(uint32_t enb_cc_idx); - uint32_t get_pending_dl_rlc_data() const; - uint32_t get_expected_dl_bitrate(uint32_t enb_cc_idx, int nof_rbgs = -1) const; + /// Get total pending bytes to be transmitted in DL. + /// The amount of CEs to transmit depends on whether enb_cc_idx is UE's PCell + uint32_t get_pending_dl_bytes(uint32_t enb_cc_idx); + rbg_interval get_required_dl_rbgs(uint32_t enb_cc_idx); + uint32_t get_pending_dl_rlc_data() const; + uint32_t get_expected_dl_bitrate(uint32_t enb_cc_idx, int nof_rbgs = -1) const; uint32_t get_pending_ul_data_total(tti_point tti_tx_ul, int this_enb_cc_idx); uint32_t get_pending_ul_new_data(tti_point tti_tx_ul, int this_enb_cc_idx); @@ -138,6 +140,8 @@ public: bool pusch_enabled(tti_point tti_rx, uint32_t enb_cc_idx, bool needs_pdcch) const; private: + srsran::interval get_requested_dl_bytes(uint32_t enb_cc_idx); + bool is_sr_triggered(); tbs_info allocate_new_dl_mac_pdu(sched_interface::dl_sched_data_t* data, diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index fcb3b7d24..44fb59d30 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -662,7 +662,7 @@ void sf_sched::set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t& continue; } sched_ue* user = ue_it->second.get(); - uint32_t data_before = user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop(); + uint32_t data_before = user->get_pending_dl_bytes(cc_cfg->enb_cc_idx); const dl_harq_proc& dl_harq = user->get_dl_harq(data_alloc.pid, cc_cfg->enb_cc_idx); bool is_newtx = dl_harq.is_empty(); @@ -678,7 +678,7 @@ void sf_sched::set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t& data_alloc.pid, data_alloc.user_mask, tbs, - user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop()); + user->get_pending_dl_bytes(cc_cfg->enb_cc_idx)); logger.warning("%s", srsran::to_c_str(str_buffer)); continue; } @@ -698,7 +698,7 @@ void sf_sched::set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t& dl_harq.nof_retx(0) + dl_harq.nof_retx(1), tbs, data_before, - user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop(), + user->get_pending_dl_bytes(cc_cfg->enb_cc_idx), get_tti_tx_dl()); logger.info("%s", srsran::to_c_str(str_buffer)); } diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 09e30e91b..86b28d429 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -767,6 +767,11 @@ rbg_interval sched_ue::get_required_dl_rbgs(uint32_t enb_cc_idx) return {min_pending_rbg, max_pending_rbg}; } +uint32_t sched_ue::get_pending_dl_bytes(uint32_t enb_cc_idx) +{ + return get_requested_dl_bytes(enb_cc_idx).stop(); +} + /** * Returns the range (min,max) of possible MAC PDU sizes. * - the lower boundary value is set based on the following conditions: 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 f1ec7c8ef..96a691ed0 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 @@ -298,6 +298,7 @@ int get_required_prb_dl(const sched_ue_cell& cell, uint32_t get_required_prb_ul(const sched_ue_cell& cell, uint32_t req_bytes) { + const static int MIN_ALLOC_BYTES = 10; /// There should be enough space for RLC header + BSR + some payload if (req_bytes == 0) { return 0; } @@ -308,11 +309,18 @@ uint32_t get_required_prb_ul(const sched_ue_cell& cell, uint32_t req_bytes) }; // find nof prbs that lead to a tbs just above req_bytes - int target_tbs = static_cast(req_bytes) + 4; + int target_tbs = std::max(static_cast(req_bytes) + 4, MIN_ALLOC_BYTES); uint32_t max_prbs = std::min(cell.tpc_fsm.max_ul_prbs(), cell.cell_cfg->nof_prb()); std::tuple ret = false_position_method(1U, max_prbs, target_tbs, compute_tbs_approx, [](int y) { return y == SRSRAN_ERROR; }); - uint32_t req_prbs = std::get<2>(ret); + uint32_t req_prbs = std::get<2>(ret); + uint32_t final_tbs = std::get<3>(ret); + while (final_tbs < MIN_ALLOC_BYTES and req_prbs < cell.cell_cfg->nof_prb()) { + // Note: If PHR<0 is limiting the max nof PRBs per UL grant, the UL grant may become too small to fit any + // data other than headers + BSR. In this edge-case, force an increase the nof required PRBs. + req_prbs++; + final_tbs = compute_tbs_approx(req_prbs); + } while (!srsran_dft_precoding_valid_prb(req_prbs) && req_prbs < cell.cell_cfg->nof_prb()) { req_prbs++; } diff --git a/srsenb/test/mac/CMakeLists.txt b/srsenb/test/mac/CMakeLists.txt index c7f8e184c..c7e721db2 100644 --- a/srsenb/test/mac/CMakeLists.txt +++ b/srsenb/test/mac/CMakeLists.txt @@ -59,6 +59,10 @@ add_executable(sched_dci_test sched_dci_test.cc) target_link_libraries(sched_dci_test srsran_common srsenb_mac srsran_mac sched_test_common) add_test(sched_dci_test sched_dci_test) +add_executable(sched_ue_cell_test sched_ue_cell_test.cc) +target_link_libraries(sched_ue_cell_test srsran_common srsenb_mac srsran_mac sched_test_common) +add_test(sched_ue_cell_test sched_ue_cell_test) + add_executable(sched_benchmark_test sched_benchmark.cc) target_link_libraries(sched_benchmark_test srsran_common srsenb_mac srsran_mac sched_test_common) add_test(sched_benchmark_test sched_benchmark_test) diff --git a/srsenb/test/mac/sched_ue_cell_test.cc b/srsenb/test/mac/sched_ue_cell_test.cc new file mode 100644 index 000000000..a6a90e81b --- /dev/null +++ b/srsenb/test/mac/sched_ue_cell_test.cc @@ -0,0 +1,75 @@ +/** + * + * \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_test_common.h" +#include "sched_test_utils.h" +#include "srsenb/hdr/stack/mac/sched_ue.h" +#include "srsran/common/test_common.h" + +using namespace srsenb; +const uint32_t seed = std::chrono::system_clock::now().time_since_epoch().count(); + +/** + * Test scenario where PHR < 0, and the UL grant size is limited. + * - The UL grant size should be the smallest possible that guarantees fitting both a BSR, RLC header, and some RLC + * payload. + */ +void test_neg_phr_scenario() +{ + sched_interface::cell_cfg_t cell_cfg = generate_default_cell_cfg(50); + cell_cfg.target_pucch_ul_sinr = 20; + cell_cfg.target_pusch_ul_sinr = 20; + cell_cfg.enable_phr_handling = true; + sched_interface::sched_args_t sched_cfg = {}; + sched_cell_params_t cell_params; + cell_params.set_cfg(0, cell_cfg, sched_cfg); + sched_interface::ue_cfg_t ue_cfg = generate_default_ue_cfg(); + + sched_ue_cell ue_cc(0x46, cell_params, tti_point(0)); + ue_cc.set_ue_cfg(ue_cfg); + + float snr = 0; + ue_cc.tpc_fsm.set_snr(snr, 0); + ue_cc.tpc_fsm.set_snr(snr, 1); + ue_cc.ul_cqi = srsran_cqi_from_snr(snr); + ue_cc.tpc_fsm.set_phr(-5); + ue_cc.new_tti(tti_point(0)); + + uint32_t req_bytes = 10000; + uint32_t pending_prbs = get_required_prb_ul(ue_cc, req_bytes); + TESTASSERT(pending_prbs < 10); // The PHR<0 is limiting the number of allocated PRBs + + uint32_t N_srs = 0; + uint32_t prb_grant_size = pending_prbs; + uint32_t nof_symb = 2 * (SRSRAN_CP_NSYMB(cell_cfg.cell.cp) - 1) - N_srs; + uint32_t nof_re = nof_symb * prb_grant_size * SRSRAN_NRE; + tbs_info tbinfo = cqi_to_tbs_ul(ue_cc, prb_grant_size, nof_re, req_bytes); + TESTASSERT(tbinfo.tbs_bytes >= 10); +} + +int main() +{ + srsenb::set_randseed(seed); + srsran::console("This is the chosen seed: %u\n", seed); + + auto& test_log = srslog::fetch_basic_logger("TEST", false); + test_log.set_level(srslog::basic_levels::info); + + // Start the log backend. + srslog::init(); + + test_neg_phr_scenario(); + + srslog::flush(); + + srsran::console("Success\n"); +}