use mini state machine for ConRes CE scheduling instead of relying that there is data in the DL buffer

This commit is contained in:
Francisco Paisana 2020-04-20 14:25:35 +01:00 committed by Francisco Paisana
parent 6de7b644ec
commit d716d8bf7e
8 changed files with 63 additions and 24 deletions

View File

@ -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<bool, uint32_t> 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);

View File

@ -126,6 +126,7 @@ public:
std::pair<bool, uint32_t> 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;

View File

@ -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());
}
}
}

View File

@ -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<bool, uint32_t> 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();

View File

@ -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<uint32_t, uint32_t> 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<uint32_t, uint32_t> 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<uint32_t, uint32_t> 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);

View File

@ -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

View File

@ -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);

View File

@ -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));
}