From c935484102368218e05a0a71b3bcd703f8df4eb8 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 9 Feb 2022 12:29:26 +0100 Subject: [PATCH] sched-nr: fix scheduler to pass nr tests Signed-off-by: Carlo Galiotto --- srsgnb/hdr/stack/mac/sched_nr_ue.h | 6 ++-- .../src/stack/mac/sched_nr_grant_allocator.cc | 17 +++++++--- srsgnb/src/stack/mac/sched_nr_ue.cc | 32 +++++++++++++------ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_ue.h b/srsgnb/hdr/stack/mac/sched_nr_ue.h index 9fcbed9b6..3ab7d1852 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_ue.h +++ b/srsgnb/hdr/stack/mac/sched_nr_ue.h @@ -61,7 +61,7 @@ public: struct pdu_builder { pdu_builder() = default; explicit pdu_builder(uint32_t cc_, ue_buffer_manager& parent_) : cc(cc_), parent(&parent_) {} - bool alloc_subpdus(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu); + bool alloc_subpdus(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu, bool reset_buf_states = false); private: uint32_t cc = SRSRAN_MAX_CARRIERS; @@ -180,9 +180,9 @@ public: ul_harq_proc* find_empty_ul_harq() { return ue->harq_ent.find_empty_ul_harq(); } /// Build PDU with MAC CEs and MAC SDUs - bool build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu) + bool build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu, bool reset_buf_states = false) { - return ue->pdu_builder.alloc_subpdus(rem_bytes, pdu); + return ue->pdu_builder.alloc_subpdus(rem_bytes, pdu, reset_buf_states); } /// Channel Information Getters diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index f1aa3e404..41e37d5b5 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -385,15 +385,22 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, uint32_t ss_id, const // Select scheduled LCIDs and update UE buffer state bwp_pdsch_slot.dl.data.emplace_back(); - // NOTE: ue.h_dl->tbs() has to be converted from bits to bytes - bool segmented_ccch_pdu = not ue.build_pdu(ue.h_dl->tbs() / 8, bwp_pdsch_slot.dl.data.back()); - if (segmented_ccch_pdu) { + // NOTES: 1) ue.h_dl->tbs() has to be converted from bits to bytes + // 2) In case of CCCH segmentation, we'll need to repeat the scheduling with a higher MCS. Hence, the + // function ue.build_pdu() will reset the LCIDs and UE buffer states as before its execution if the flag + // "mcstbs() / 8, bwp_pdsch_slot.dl.data.back(), mcs < min_MCS_ccch); + if (segmented_ccch_pdu and mcs < min_MCS_ccch) { // In case of segmented PDU for CCCH, set minimum MCS to 4 and re-run the outer while loop bwp_pdsch_slot.dl.data.pop_back(); mcs = min_MCS_ccch; pdcch.dci.mcs = mcs; - logger.warning( - "SCHED: MCS increased to min value %d to allocate SRB0/CCCH for rnti=0x%x", min_MCS_ccch, ue->rnti); + logger.info("SCHED: MCS increased to min value %d to allocate SRB0/CCCH for rnti=0x%x", min_MCS_ccch, ue->rnti); + } else if (segmented_ccch_pdu /* and mcs >= min_MCS_ccch */) { + // With MCS >= then min_MCS_ccch, it is not possible to allocate SRB0/CCCH without PDU segmentation + logger.error("SCHED: Insufficient resources to allocate SRB0/CCCH without PDU segmentation for rnti=0x%x", + ue->rnti); + break; } else { break; } diff --git a/srsgnb/src/stack/mac/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc index 061ea98e9..549da55d6 100644 --- a/srsgnb/src/stack/mac/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -27,8 +27,18 @@ int ue_buffer_manager::get_dl_tx_total() const return total_bytes; } -// Return true if there is no SRB0/CCCH MAC PDU segmentation, false otherwise -bool ue_buffer_manager::pdu_builder::alloc_subpdus(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu) +/** + * @brief Allocates LCIDs and update US buffer states depending on available resources and checks if there is SRB0/CCCH + MAC PDU segmentation + + * @param rem_bytes TBS to be filled with MAC CEs and MAC SDUs [in bytes] + * @param reset_buf_states If true, when there is SRB0/CCCH MAC PDU segmentation, restore the UE buffers and scheduled + LCIDs as before running this function + * @return true if there is no SRB0/CCCH MAC PDU segmentation, false otherwise + */ +bool ue_buffer_manager::pdu_builder::alloc_subpdus(uint32_t rem_bytes, + sched_nr_interface::dl_pdu_t& pdu, + bool reset_buf_states) { // In case of SRB0/CCCH PDUs, we need to check whether there is PDU segmentation; if LCID = 0 has emtpy buffer, no // need to perform this check @@ -47,10 +57,10 @@ bool ue_buffer_manager::pdu_builder::alloc_subpdus(uint32_t rem_bytes, sched_nr_ rem_bytes -= size_ce; pdu.subpdus.push_back(ce.lcid); // If there is possibility of CCCH segmentation, we need to save the MAC CEs in a tmp queue to be later restored - if (check_ccch_pdu_segmentation) { + if (check_ccch_pdu_segmentation and reset_buf_states) { restore_ces.push_back(parent->pending_ces.front()); - parent->pending_ces.pop_front(); } + parent->pending_ces.pop_front(); } } @@ -60,12 +70,16 @@ bool ue_buffer_manager::pdu_builder::alloc_subpdus(uint32_t rem_bytes, sched_nr_ // Verify if the TBS is big enough to store the entire CCCH buffer // Note: (pending_lcid_bytes > rem_bytes) implies (check_ccch_pdu_segmentation == true) if (lcid == srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CCCH and pending_lcid_bytes > rem_bytes) { - // restore the MAC CEs as they were at the beginning of the function - for (ce_t ce : restore_ces) { - parent->pending_ces.push_back(ce); + if (reset_buf_states) { + // restore the MAC CEs as they were at the beginning of the function + for (ce_t ce : restore_ces) { + parent->pending_ces.push_back(ce); + } + // double check if this line is required + pdu.subpdus.clear(); + } else { + pdu.subpdus.push_back(lcid); } - // double check if this line is required - pdu.subpdus.clear(); return false; } if (pending_lcid_bytes > 0) {