diff --git a/srsenb/hdr/stack/mac/scheduler_harq.h b/srsenb/hdr/stack/mac/scheduler_harq.h index 0f1ac67ed..867faf9b9 100644 --- a/srsenb/hdr/stack/mac/scheduler_harq.h +++ b/srsenb/hdr/stack/mac/scheduler_harq.h @@ -161,6 +161,11 @@ public: //! Get UL Harq for a given tti_tx_ul ul_harq_proc* get_ul_harq(uint32_t tti_tx_ul); + /** + * Set ACK state for UL Harq Proc + */ + std::pair set_ul_crc(srslte::tti_point tti_tx_ul, uint32_t tb_idx, bool ack_); + //! Resets pending harq ACKs and cleans UL Harqs with maxretx == 0 void reset_pending_data(uint32_t tti_rx); diff --git a/srsenb/hdr/stack/mac/scheduler_ue.h b/srsenb/hdr/stack/mac/scheduler_ue.h index d5f6b3ed0..d42299d0d 100644 --- a/srsenb/hdr/stack/mac/scheduler_ue.h +++ b/srsenb/hdr/stack/mac/scheduler_ue.h @@ -126,6 +126,7 @@ public: std::pair get_cell_index(uint32_t enb_cc_idx) const; const sched_interface::ue_cfg_t& get_ue_cfg() const { return cfg; } uint32_t get_aggr_level(uint32_t ue_cc_idx, uint32_t nof_bits); + void sched_conres_ce(uint32_t msg3_tti_tx_ul); /******************************************************* * Functions used by scheduler metric objects @@ -142,7 +143,7 @@ public: dl_harq_proc* get_pending_dl_harq(uint32_t tti_tx_dl, uint32_t cc_idx); dl_harq_proc* get_empty_dl_harq(uint32_t tti_tx_dl, uint32_t cc_idx); - ul_harq_proc* get_ul_harq(uint32_t tti, uint32_t cc_idx); + ul_harq_proc* get_ul_harq(uint32_t tti, uint32_t ue_cc_idx); /******************************************************* * Functions used by the scheduler carrier object @@ -261,7 +262,13 @@ private: uint32_t max_msg3retx = 0; /* User State */ - bool conres_ce_pending = true; + enum class ra_state_t { + msg3_sched_pending, + wait_msg3_ack, + conres_sched_pending, + conres_sent + } conres_state = ra_state_t::msg3_sched_pending; + uint32_t msg3_pid = 0; int next_tpc_pusch = 0; int next_tpc_pucch = 0; diff --git a/srsenb/src/stack/mac/scheduler_carrier.cc b/srsenb/src/stack/mac/scheduler_carrier.cc index aaa104448..09976721a 100644 --- a/srsenb/src/stack/mac/scheduler_carrier.cc +++ b/srsenb/src/stack/mac/scheduler_carrier.cc @@ -240,10 +240,11 @@ void ra_sched::ul_sched(sf_sched* sf_dl_sched, sf_sched* sf_msg3_sched) 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 { + if (user_it != ue_db->end() and sf_msg3_sched->alloc_msg3(&user_it->second, msg3grant)) { log_h->debug("SCHED: Queueing Msg3 for rnti=0x%x at tti=%d\n", crnti, sf_msg3_sched->get_tti_tx_ul()); + user_it->second.sched_conres_ce(sf_msg3_sched->get_tti_tx_ul()); + } else { + log_h->error("SCHED: Failed to allocate Msg3 for rnti=0x%x at tti=%d\n", crnti, sf_msg3_sched->get_tti_tx_ul()); } } } diff --git a/srsenb/src/stack/mac/scheduler_harq.cc b/srsenb/src/stack/mac/scheduler_harq.cc index 8914f3adf..6cfa4ced1 100644 --- a/srsenb/src/stack/mac/scheduler_harq.cc +++ b/srsenb/src/stack/mac/scheduler_harq.cc @@ -366,10 +366,17 @@ ul_harq_proc* harq_entity::get_ul_harq(uint32_t tti_tx_ul) return &ul_harqs[tti_tx_ul % ul_harqs.size()]; } +std::pair harq_entity::set_ul_crc(srslte::tti_point tti_rx, uint32_t tb_idx, bool ack_) +{ + ul_harq_proc* h = get_ul_harq(tti_rx.to_uint()); + uint32_t pid = h->get_id(); + return {h->set_ack(tb_idx, ack_), pid}; +} + void harq_entity::reset_pending_data(uint32_t tti_rx) { - tti_point tti_tx_ul = tti_point{tti_rx} + FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS; - tti_point tti_tx_dl = tti_point{tti_rx} + FDD_HARQ_DELAY_UL_MS; + tti_point tti_tx_ul = srslte::to_tx_ul(tti_point{tti_rx}); + tti_point tti_tx_dl = srslte::to_tx_dl(tti_point{tti_rx}); // Reset ACK state of UL Harq get_ul_harq(tti_tx_ul.to_uint())->reset_pending_data(); diff --git a/srsenb/src/stack/mac/scheduler_ue.cc b/srsenb/src/stack/mac/scheduler_ue.cc index f476492b1..c5a17ba01 100644 --- a/srsenb/src/stack/mac/scheduler_ue.cc +++ b/srsenb/src/stack/mac/scheduler_ue.cc @@ -144,8 +144,7 @@ void sched_ue::set_cfg(const sched_interface::ue_cfg_t& cfg_) carriers[ue_idx] = sched_ue_carrier{cfg, (*cell_params_list)[cc_cfg.enb_cc_idx], rnti, ue_idx}; if (ue_idx == 0) { // PCell was changed possibly due to handover. Schedule a new ConRes CE to be transmitted after the Msg3 - conres_ce_pending = true; - lch[0].buf_tx = std::max(lch[0].buf_tx, 1); // TODO: find a cleaner way to schedule conres CE + conres_state = ra_state_t::conres_sched_pending; log_h->info("SCHED: PCell has changed. ConRes CE scheduled\n"); } } else { @@ -171,7 +170,7 @@ void sched_ue::reset() buf_ul = 0; phy_config_dedicated_enabled = false; cqi_request_tti = 0; - conres_ce_pending = true; + conres_state = ra_state_t::msg3_sched_pending; carriers.clear(); // erase all bearers @@ -306,9 +305,13 @@ void sched_ue::set_ul_crc(srslte::tti_point tti_rx, uint32_t enb_cc_idx, bool cr { auto p = get_cell_index(enb_cc_idx); if (p.first) { - srslte::tti_point tti_tx_ul = srslte::to_tx_ul(tti_rx); - if (not get_ul_harq(tti_tx_ul.to_uint(), p.second)->set_ack(0, crc_res)) { - log_h->warning("Received UL CRC for invalid tti_tx_ul=%d\n", (int)tti_tx_ul.to_uint()); + auto ret = carriers[p.second].harq_ent.set_ul_crc(tti_rx, 0, crc_res); + if (not ret.first) { + log_h->warning("Received UL CRC for invalid tti_rx=%d\n", (int)tti_rx.to_uint()); + } else { + if (conres_state == ra_state_t::wait_msg3_ack and ret.second == msg3_pid and crc_res) { + conres_state = ra_state_t::conres_sched_pending; + } } } else { log_h->warning("Received UL CRC for invalid cell index %d\n", enb_cc_idx); @@ -468,7 +471,7 @@ int sched_ue::generate_format1(uint32_t pid, if (is_conres_ce_pending()) { data->pdu[0][data->nof_pdu_elems[0]].lcid = srslte::sch_subh::CON_RES_ID; data->nof_pdu_elems[0]++; - conres_ce_pending = false; + conres_state = ra_state_t::conres_sent; Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti); } @@ -810,7 +813,7 @@ bool sched_ue::needs_cqi_unlocked(uint32_t tti, uint32_t cc_idx, bool will_be_se bool sched_ue::is_conres_ce_pending() const { - return conres_ce_pending and bearer_is_dl(&lch[0]) and (lch[0].buf_retx > 0 or lch[0].buf_tx > 0); + return conres_state == ra_state_t::conres_sched_pending; } /// Use this function in the dl-metric to get the bytes to be scheduled. It accounts for the UE data, @@ -892,13 +895,17 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id log_h->error("SRB0 must always be activated for DL\n"); return {0, 0}; } + if (conres_state == ra_state_t::msg3_sched_pending or conres_state == ra_state_t::wait_msg3_ack) { + return {0, 0}; + } + uint32_t max_data = 0, min_data = 0; uint32_t srb0_data = 0, rb_data = 0, sum_ce_data = 0; bool is_dci_format1 = get_dci_format() == SRSLTE_DCI_FORMAT1; if (is_dci_format1 and (lch[0].buf_tx > 0 or lch[0].buf_retx > 0)) { srb0_data = compute_sdu_total_bytes(0, lch[0].buf_retx); srb0_data += compute_sdu_total_bytes(0, lch[0].buf_tx); - if (conres_ce_pending) { + if (is_conres_ce_pending()) { sum_ce_data = sched_utils::conres_ce_size + ce_subheader_size; } } @@ -920,7 +927,7 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id /* Set Minimum boundary */ if (srb0_data > 0) { min_data = srb0_data; - if (conres_ce_pending) { + if (is_conres_ce_pending()) { min_data += sched_utils::conres_ce_size + ce_subheader_size; } } else { @@ -940,6 +947,9 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id */ uint32_t sched_ue::get_pending_dl_new_data() { + if (conres_state == ra_state_t::msg3_sched_pending or conres_state == ra_state_t::wait_msg3_ack) { + return 0; + } uint32_t pending_data = 0; for (int i = 0; i < sched_interface::MAX_LC; i++) { if (bearer_is_dl(&lch[i])) { @@ -1085,6 +1095,12 @@ uint32_t sched_ue::get_aggr_level(uint32_t ue_cc_idx, uint32_t nof_bits) return carriers[ue_cc_idx].get_aggr_level(nof_bits); } +void sched_ue::sched_conres_ce(uint32_t msg3_tti_tx_ul) +{ + msg3_pid = carriers[0].harq_ent.get_ul_harq(msg3_tti_tx_ul)->get_id(); + conres_state = ra_state_t::wait_msg3_ack; +} + void sched_ue::finish_tti(const tti_params_t& tti_params, uint32_t enb_cc_idx) { auto p = get_cell_index(enb_cc_idx); diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 5e0ce6f8f..d61699837 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -37,8 +37,10 @@ public: int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override { return 0; } void phy_config_enabled(uint16_t rnti, bool enabled) override {} void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch) override - { - } + {} + uint16_t allocate_rnti() override { return last_rnti++; } + + uint16_t last_rnti = 70; }; class rlc_dummy : public rlc_interface_rrc diff --git a/srsenb/test/mac/scheduler_ca_test.cc b/srsenb/test/mac/scheduler_ca_test.cc index 6d00b27d8..0a21d4d3c 100644 --- a/srsenb/test/mac/scheduler_ca_test.cc +++ b/srsenb/test/mac/scheduler_ca_test.cc @@ -196,15 +196,16 @@ int test_scell_activation(test_scell_activation_params params) // Event: Wait for UE to receive and ack CE. Send cqi==0, which should not activate the SCell uint32_t cqi = 0; - for (uint32_t i = 0; i < FDD_HARQ_DELAY_UL_MS; ++i) { - tester.dl_cqi_info(tester.tti_info.tti_params.tti_rx, rnti1, 1, cqi); - generator.step_tti(); + for (uint32_t cidx = 1; cidx < cc_idxs.size(); ++cidx) { + for (uint32_t i = 0; i < FDD_HARQ_DELAY_UL_MS; ++i) { + tester.dl_cqi_info(tester.tti_info.tti_params.tti_rx, rnti1, cc_idxs[cidx], cqi); + generator.step_tti(); + } } tester.test_next_ttis(generator.tti_events); // The UE should now have received the CE // Event: Generate a bit more data, it should *not* go through SCells until we send a CQI - tester.dl_cqi_info(tester.tti_info.tti_params.tti_rx, rnti1, 1, cqi); generate_data(5, P_dl, P_ul_sr, randf()); tester.test_next_ttis(generator.tti_events); TESTASSERT(tester.sched_stats->users[rnti1].tot_dl_sched_data[params.pcell_idx] > 0); diff --git a/srsenb/test/mac/scheduler_test_common.cc b/srsenb/test/mac/scheduler_test_common.cc index d3a826b5b..038cdcf91 100644 --- a/srsenb/test/mac/scheduler_test_common.cc +++ b/srsenb/test/mac/scheduler_test_common.cc @@ -831,7 +831,7 @@ int common_sched_tester::schedule_acks() if (ack_data.ul_harq.nof_retx(0) == 0) { ack_data.ack = randf() > sim_args0.P_retx; } else { - ack_data.ack = ack_data.ul_harq.nof_retx(0) == 3; + ack_data.ack = ack_data.ul_harq.nof_retx(0) == 2; } to_ul_ack.insert(std::make_pair(ack_data.tti_tx_ul, ack_data)); }