diff --git a/srsenb/hdr/stack/mac/scheduler_carrier.h b/srsenb/hdr/stack/mac/scheduler_carrier.h index 445cd0a73..1748e36cb 100644 --- a/srsenb/hdr/stack/mac/scheduler_carrier.h +++ b/srsenb/hdr/stack/mac/scheduler_carrier.h @@ -116,10 +116,9 @@ public: explicit ra_sched(const sched_cell_params_t& cfg_, std::map& ue_db_); void dl_sched(sf_sched* tti_sched); - void ul_sched(sf_sched* tti_sched); + void ul_sched(sf_sched* sf_dl_sched, sf_sched* sf_msg3_sched); int dl_rach_info(dl_sched_rar_info_t rar_info); void reset(); - void sched_msg3(sf_sched* sf_msg3_sched, const sched_interface::dl_sched_res_t& dl_sched_result); private: // args diff --git a/srsenb/hdr/stack/mac/scheduler_grid.h b/srsenb/hdr/stack/mac/scheduler_grid.h index 94c87579b..8047760b4 100644 --- a/srsenb/hdr/stack/mac/scheduler_grid.h +++ b/srsenb/hdr/stack/mac/scheduler_grid.h @@ -235,9 +235,10 @@ public: alloc_outcome_t alloc_paging(uint32_t aggr_lvl, uint32_t paging_payload); std::pair alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar_grant); bool reserve_dl_rbgs(uint32_t rbg_start, uint32_t rbg_end) { return tti_alloc.reserve_dl_rbgs(rbg_start, rbg_end); } + const std::vector& get_allocated_rars() const { return rar_allocs; } // UL alloc methods - alloc_outcome_t alloc_msg3(sched_ue* user, const pending_msg3_t& msg3); + alloc_outcome_t alloc_msg3(sched_ue* user, const sched_interface::dl_sched_rar_grant_t& rargrant); alloc_outcome_t alloc_ul(sched_ue* user, ul_harq_proc::ul_alloc_t alloc, sf_sched::ul_alloc_t::type_t alloc_type, uint32_t mcs = 0); bool reserve_ul_prbs(const prbmask_t& ulmask, bool strict) { return tti_alloc.reserve_ul_prbs(ulmask, strict); } diff --git a/srsenb/src/stack/mac/scheduler_carrier.cc b/srsenb/src/stack/mac/scheduler_carrier.cc index 8a42a222f..39188d610 100644 --- a/srsenb/src/stack/mac/scheduler_carrier.cc +++ b/srsenb/src/stack/mac/scheduler_carrier.cc @@ -149,7 +149,7 @@ ra_sched::ra_sched(const sched_cell_params_t& cfg_, std::map // Schedules RAR // On every call to this function, we schedule the oldest RAR which is still within the window. If outside the window we // discard it. -void ra_sched::dl_sched(srsenb::sf_sched* tti_sched) +void ra_sched::dl_sched(sf_sched* tti_sched) { uint32_t tti_tx_dl = tti_sched->get_tti_tx_dl(); rar_aggr_level = 2; @@ -179,22 +179,24 @@ void ra_sched::dl_sched(srsenb::sf_sched* tti_sched) // Try to schedule DCI + RBGs for RAR Grant std::pair ret = tti_sched->alloc_rar(rar_aggr_level, rar); - - if (ret.first == alloc_outcome_t::SUCCESS) { - // if all RAR grant allocations were successful - if (ret.second == rar.nof_grants) { - // Remove pending RAR - pending_rars.pop_front(); - } else if (ret.second > 0) { - // keep the RAR grants that were not scheduled, so we can schedule in next TTI - std::copy(&rar.msg3_grant[ret.second], &rar.msg3_grant[rar.nof_grants], &rar.msg3_grant[0]); - rar.nof_grants -= ret.second; - } - } else if (ret.first == alloc_outcome_t::RB_COLLISION) { + if (ret.first == alloc_outcome_t::RB_COLLISION) { // there are not enough RBs for RAR or Msg3 allocation. We can skip this TTI return; } - // try to scheduler next RAR with different RA-RNTI + if (ret.first != alloc_outcome_t::SUCCESS) { + // try to scheduler next RAR with different RA-RNTI + continue; + } + + uint32_t nof_rar_allocs = ret.second; + if (nof_rar_allocs == rar.nof_grants) { + // all RAR grants were allocated. Remove pending RAR + pending_rars.pop_front(); + } else { + // keep the RAR grants that were not scheduled, so we can schedule in next TTI + std::copy(&rar.msg3_grant[nof_rar_allocs], &rar.msg3_grant[rar.nof_grants], &rar.msg3_grant[0]); + rar.nof_grants -= nof_rar_allocs; + } } } @@ -231,34 +233,31 @@ int ra_sched::dl_rach_info(dl_sched_rar_info_t rar_info) return SRSLTE_SUCCESS; } -void ra_sched::reset() +//! Schedule Msg3 grants in UL based on allocated RARs +void ra_sched::ul_sched(sf_sched* sf_dl_sched, sf_sched* sf_msg3_sched) { - pending_rars.clear(); -} + const std::vector& alloc_rars = sf_dl_sched->get_allocated_rars(); -void ra_sched::sched_msg3(sf_sched* sf_msg3_sched, const sched_interface::dl_sched_res_t& dl_sched_result) -{ - // Go through all scheduled RARs, and pre-allocate Msg3s in UL channel accordingly - for (uint32_t i = 0; i < dl_sched_result.nof_rar_elems; ++i) { - for (uint32_t j = 0; j < dl_sched_result.rar[i].nof_grants; ++j) { - auto& grant = dl_sched_result.rar[i].msg3_grant[j]; + for (const auto& rar : alloc_rars) { + for (uint32_t j = 0; j < rar.rar_grant.nof_grants; ++j) { + const auto& msg3grant = rar.rar_grant.msg3_grant[j]; - sf_sched::pending_msg3_t msg3; - srslte_ra_type2_from_riv(grant.grant.rba, &msg3.L, &msg3.n_prb, cc_cfg->nof_prb(), cc_cfg->nof_prb()); - msg3.mcs = grant.grant.trunc_mcs; - msg3.rnti = grant.data.temp_crnti; - - auto it = ue_db->find(msg3.rnti); - if (it == ue_db->end() or not sf_msg3_sched->alloc_msg3(&it->second, msg3)) { - log_h->error( - "SCHED: Failed to allocate Msg3 for rnti=0x%x at tti=%d\n", msg3.rnti, sf_msg3_sched->get_tti_tx_ul()); + uint16_t crnti = msg3grant.data.temp_crnti; + auto user_it = ue_db->find(crnti); + if (user_it == ue_db->end() or not sf_msg3_sched->alloc_msg3(&user_it->second, msg3grant)) { + log_h->error("SCHED: Failed to allocate Msg3 for rnti=0x%x at tti=%d\n", crnti, sf_msg3_sched->get_tti_tx_ul()); } else { - log_h->debug("SCHED: Queueing Msg3 for rnti=0x%x at tti=%d\n", msg3.rnti, sf_msg3_sched->get_tti_tx_ul()); + log_h->debug("SCHED: Queueing Msg3 for rnti=0x%x at tti=%d\n", crnti, sf_msg3_sched->get_tti_tx_ul()); } } } } +void ra_sched::reset() +{ + pending_rars.clear(); +} + /******************************************************* * Carrier scheduling *******************************************************/ @@ -338,6 +337,10 @@ const sf_sched_result& sched::carrier_sched::generate_tti_result(uint32_t tti_rx /* Schedule RAR */ ra_sched_ptr->dl_sched(tti_sched); + + /* Schedule Msg3 */ + sf_sched* sf_msg3_sched = get_sf_sched(tti_rx + MSG3_DELAY_MS); + ra_sched_ptr->ul_sched(tti_sched, sf_msg3_sched); } /* Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion */ @@ -355,12 +358,6 @@ const sf_sched_result& sched::carrier_sched::generate_tti_result(uint32_t tti_rx /* Select the winner DCI allocation combination, store all the scheduling results */ tti_sched->generate_sched_results(sf_result); - /* Enqueue Msg3s derived from allocated RARs */ - if (dl_active) { - sf_sched* sf_msg3_sched = get_sf_sched(tti_rx + MSG3_DELAY_MS); - ra_sched_ptr->sched_msg3(sf_msg3_sched, sf_result->dl_sched_result); - } - /* Reset ue harq pending ack state, clean-up blocked pids */ for (auto& user : *ue_db) { user.second.finish_tti(sf_result->tti_params, enb_cc_idx); diff --git a/srsenb/src/stack/mac/scheduler_grid.cc b/srsenb/src/stack/mac/scheduler_grid.cc index 79f0c549d..8bdbbbc6a 100644 --- a/srsenb/src/stack/mac/scheduler_grid.cc +++ b/srsenb/src/stack/mac/scheduler_grid.cc @@ -558,8 +558,8 @@ std::pair sf_sched::alloc_rar(uint32_t aggr_lvl, cons last_msg3_prb += msg3_grant_size; } - rar_allocs.emplace_back(ret2.second, rar_grant); + break; } if (ret.first != alloc_outcome_t::SUCCESS) { @@ -898,13 +898,17 @@ void sf_sched::set_ul_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul } } -alloc_outcome_t sf_sched::alloc_msg3(sched_ue* user, const pending_msg3_t& msg3) +alloc_outcome_t sf_sched::alloc_msg3(sched_ue* user, const sched_interface::dl_sched_rar_grant_t& rargrant) { - // Allocate RBGs and HARQ for pending Msg3 - ul_harq_proc::ul_alloc_t msg3_alloc = {msg3.n_prb, msg3.L}; - alloc_outcome_t ret = alloc_ul(user, msg3_alloc, sf_sched::ul_alloc_t::MSG3, msg3.mcs); + // Derive PRBs from allocated RAR grants + ul_harq_proc::ul_alloc_t msg3_alloc = {}; + srslte_ra_type2_from_riv( + rargrant.grant.rba, &msg3_alloc.L, &msg3_alloc.RB_start, cc_cfg->nof_prb(), cc_cfg->nof_prb()); + + alloc_outcome_t ret = alloc_ul(user, msg3_alloc, sf_sched::ul_alloc_t::MSG3, rargrant.grant.trunc_mcs); if (not ret) { - log_h->warning("SCHED: Could not allocate msg3 within (%d,%d)\n", msg3.n_prb, msg3.n_prb + msg3.L); + log_h->warning( + "SCHED: Could not allocate msg3 within (%d,%d)\n", msg3_alloc.RB_start, msg3_alloc.RB_start + msg3_alloc.L); } return ret; } diff --git a/srsenb/test/mac/scheduler_test_common.cc b/srsenb/test/mac/scheduler_test_common.cc index 6a3a4ad49..cd27c10d9 100644 --- a/srsenb/test/mac/scheduler_test_common.cc +++ b/srsenb/test/mac/scheduler_test_common.cc @@ -388,40 +388,26 @@ int user_state_sched_tester::test_ra(uint32_t enb_ uint16_t rnti = iter.first; ue_state& userinfo = iter.second; - // No UL allocations before Msg3 - for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) { - if (ul_result.pusch[i].dci.rnti == rnti) { - CONDERROR(not userinfo.rar_tic.is_valid(), "No UL allocs allowed before RAR\n"); - CONDERROR(ul_result.pusch[i].needs_pdcch and not userinfo.msg3_tic.is_valid() and - userinfo.msg3_tic.tti_rx() > tic.tti_rx(), - "No UL newtxs allocs allowed before Msg3 Rx\n"); - tti_counter msg3_tic = userinfo.rar_tic + FDD_HARQ_DELAY_DL_MS + MSG3_DELAY_MS; - CONDERROR(msg3_tic > tic.tic_tx_ul(), "No UL allocs allowed before Msg3 alloc\n"); - } - } - - // No DL data allocations before Msg3 is received - for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) { - if (dl_result.data[i].dci.rnti == rnti) { - CONDERROR(not userinfo.msg3_tic.is_valid(), "No DL data alloc allowed before Msg3 alloc\n"); - CONDERROR(tic + FDD_HARQ_DELAY_DL_MS < userinfo.msg3_tic, "Msg4 cannot be tx without Msg3 being acked\n"); - } - } - uint32_t primary_cc_idx = userinfo.user_cfg.supported_cc_list[0].enb_cc_idx; if (enb_cc_idx != primary_cc_idx) { // only check for RAR/Msg3 presence for a UE's PCell continue; } - // No RAR allocations outside of rar_window + /* TEST: RAR allocation */ std::array rar_window = { userinfo.prach_tic + 3, userinfo.prach_tic + 3 + (int)cell_params[primary_cc_idx].prach_rar_window}; + tti_counter tic_tx_dl = tic.tic_tx_dl(); + tti_counter tic_tx_ul = tic.tic_tx_ul(); + bool is_in_rar_window = tic_tx_dl >= rar_window[0] and tic_tx_dl <= rar_window[1]; - tti_counter tic_tx_dl = tic.tic_tx_dl(); - CONDERROR(not userinfo.rar_tic.is_valid() and tic.tic_tx_dl() > rar_window[1], - "RAR not scheduled within the RAR Window\n"); - if (tic_tx_dl <= rar_window[1] and tic_tx_dl >= rar_window[0]) { + if (not is_in_rar_window) { + CONDERROR(not userinfo.rar_tic.is_valid() and tic_tx_dl > rar_window[1], + "RAR not scheduled within the RAR Window\n"); + for (uint32_t i = 0; i < dl_result.nof_rar_elems; ++i) { + CONDERROR(dl_result.rar[i].dci.rnti == rnti, "No RAR allocations allowed outside of user RAR window\n"); + } + } else { // Inside RAR window for (uint32_t i = 0; i < dl_result.nof_rar_elems; ++i) { for (uint32_t j = 0; j < dl_result.rar[i].nof_grants; ++j) { @@ -437,36 +423,62 @@ int user_state_sched_tester::test_ra(uint32_t enb_ } /* TEST: Check Msg3 */ - if (userinfo.rar_tic.is_valid()) { + if (userinfo.rar_tic.is_valid() and not userinfo.msg3_tic.is_valid()) { + // RAR scheduled, Msg3 not yet scheduled tti_counter expected_msg3_tti = userinfo.rar_tic + FDD_HARQ_DELAY_DL_MS + MSG3_DELAY_MS; - if (expected_msg3_tti == tic.tic_tx_ul()) { + CONDERROR(expected_msg3_tti < tic_tx_ul and not userinfo.msg3_tic.is_valid(), "No UL msg3 alloc was made\n"); + + if (expected_msg3_tti == tic_tx_ul) { + // Msg3 should exist for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) { if (ul_result.pusch[i].dci.rnti == rnti) { CONDERROR(userinfo.msg3_tic.is_valid(), "Only one Msg3 allowed per user\n"); CONDERROR(ul_result.pusch[i].needs_pdcch, "Msg3 allocations do not require PDCCH\n"); CONDERROR(userinfo.msg3_riv != ul_result.pusch[i].dci.type2_alloc.riv, "The Msg3 was not allocated in the expected PRBs.\n"); - userinfo.msg3_tic = tic.tic_tx_ul(); + userinfo.msg3_tic = tic_tx_ul; msg3_count++; } } - } else if (expected_msg3_tti < tic.tic_tx_ul()) { - CONDERROR(not userinfo.msg3_tic.is_valid(), "No UL msg3 allocation was made\n"); } } - // Find any Msg4 Allocation - for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) { - if (dl_result.data[i].dci.rnti == rnti) { - for (uint32_t j = 0; j < dl_result.data[i].nof_pdu_elems[0]; ++j) { - if (dl_result.data[i].pdu[0][j].lcid == srslte::sch_subh::CON_RES_ID) { - // ConRes found - CONDERROR(dl_result.data[i].dci.format != SRSLTE_DCI_FORMAT1, "ConRes must be format1\n"); - CONDERROR(userinfo.msg4_tic.is_valid(), "Duplicate ConRes CE for the same rnti\n"); - userinfo.msg4_tic = tic.tic_tx_dl(); + /* TEST: Check Msg4 */ + if (userinfo.msg3_tic.is_valid() and not userinfo.msg4_tic.is_valid()) { + // Msg3 scheduled, but Msg4 not yet scheduled + for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) { + if (dl_result.data[i].dci.rnti == rnti) { + CONDERROR(tic < userinfo.msg3_tic, "Msg4 cannot be scheduled without Msg3 being tx\n"); + for (uint32_t j = 0; j < dl_result.data[i].nof_pdu_elems[0]; ++j) { + if (dl_result.data[i].pdu[0][j].lcid == srslte::sch_subh::CON_RES_ID) { + // ConRes found + CONDERROR(dl_result.data[i].dci.format != SRSLTE_DCI_FORMAT1, "ConRes must be format1\n"); + CONDERROR(userinfo.msg4_tic.is_valid(), "Duplicate ConRes CE for the same rnti\n"); + userinfo.msg4_tic = tic_tx_dl; + } } } - CONDERROR(not userinfo.msg4_tic.is_valid(), "Data allocs are not allowed without first receiving ConRes\n"); + } + } + + /* TEST: Txs out of place */ + if (not userinfo.msg4_tic.is_valid()) { + // Msg4 not yet received by user + for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) { + CONDERROR(dl_result.data[i].dci.rnti == rnti, "No DL data allocs allowed before Msg4 is scheduled\n"); + } + if (userinfo.msg3_tic.is_valid() and userinfo.msg3_tic != tic_tx_ul) { + // Msg3 scheduled. No UL alloc allowed unless it is a newtx (the Msg3 itself) + for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) { + // Needs PDCCH - filters out UL retxs + CONDERROR(ul_result.pusch[i].needs_pdcch and ul_result.pusch[i].dci.rnti == rnti, + "No UL newtxs allowed before user received Msg4\n"); + } + } else if (not userinfo.msg3_tic.is_valid()) { + // Not Msg3 sched TTI + for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) { + CONDERROR(ul_result.pusch[i].dci.rnti == rnti, "No UL newtxs allowed before user received Msg4\n"); + } } } }