Skip to content

Commit a420c55

Browse files
committed
sched: add fix for HARQs trapped in pending retx
1 parent 9b9c5dc commit a420c55

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

lib/scheduler/ue_scheduling/cell_harq_manager.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include "cell_harq_manager.h"
12+
#include "../cell/resource_grid_util.h"
1213
#include "srsran/scheduler/scheduler_slot_handler.h"
1314

1415
using namespace srsran;
@@ -46,21 +47,41 @@ cell_harq_repository<IsDl>::cell_harq_repository(unsigned max_ues,
4647
ues[i].harqs.reserve(MAX_NOF_HARQS);
4748
}
4849

49-
const unsigned RING_SIZE = 320; // TODO: use function to define this value. It must account the timeout arg and k
50-
// values
51-
harq_timeout_wheel.resize(RING_SIZE);
50+
harq_timeout_wheel.resize(get_allocator_ring_size_gt_min(max_ack_wait_timeout + get_max_slot_ul_alloc_delay(0)));
5251
}
5352

5453
template <bool IsDl>
5554
void cell_harq_repository<IsDl>::slot_indication(slot_point sl_tx)
5655
{
56+
last_sl_ind = sl_tx;
57+
5758
// Handle HARQs that timed out.
5859
auto& harqs_timing_out = harq_timeout_wheel[sl_tx.to_uint() % harq_timeout_wheel.size()];
5960
while (not harqs_timing_out.empty()) {
6061
handle_harq_ack_timeout(harqs_timing_out.front(), sl_tx);
6162
}
6263

63-
last_sl_ind = sl_tx;
64+
// Handle HARQs with pending reTx that are trapped (never scheduled). This is a safety mechanism to account for a
65+
// potential bug or limitation in the scheduler policy that is leaving HARQ processes with pending reTxs for too long.
66+
// Note: we assume that the list is ordered based on when they were last ACKed.
67+
while (not harq_pending_retx_list.empty()) {
68+
auto& h = harq_pending_retx_list.front();
69+
srsran_sanity_check(h.status == harq_state_t::pending_retx, "HARQ process in wrong state");
70+
// [Implementation-defined] Maximum time we give to the scheduler policy to retransmit a HARQ process.
71+
const unsigned max_nof_slots_for_retx = last_sl_ind.nof_slots_per_system_frame() / 4;
72+
if (last_sl_ind < (h.slot_ack + max_nof_slots_for_retx)) {
73+
break;
74+
}
75+
76+
// HARQ is trapped. Remove it.
77+
logger.warning(
78+
"rnti={} h_id={}: Discarding {} HARQ. Cause: Too much time has passed since the last HARQ "
79+
"transmission. The scheduler policy is likely not prioritizing retransmissions of old HARQ processes.",
80+
h.rnti,
81+
h.h_id,
82+
IsDl ? "DL" : "UL");
83+
dealloc_harq(h);
84+
}
6485
}
6586

6687
template <bool IsDl>
@@ -306,6 +327,15 @@ unsigned cell_harq_repository<IsDl>::find_ue_harq_in_state(du_ue_index_t ue_idx,
306327
template struct harq_utils::cell_harq_repository<true>;
307328
template struct harq_utils::cell_harq_repository<false>;
308329

330+
template <bool IsDl>
331+
void harq_utils::base_harq_process_handle<IsDl>::cancel_retxs()
332+
{
333+
harq_repo->cancel_retxs(fetch_impl());
334+
}
335+
336+
template class harq_utils::base_harq_process_handle<true>;
337+
template class harq_utils::base_harq_process_handle<false>;
338+
309339
// Cell HARQ manager.
310340

311341
cell_harq_manager::cell_harq_manager(unsigned max_ues,
@@ -453,11 +483,6 @@ void dl_harq_process_handle::increment_pucch_counter()
453483
++fetch_impl().pucch_ack_to_receive;
454484
}
455485

456-
void dl_harq_process_handle::cancel_retxs()
457-
{
458-
harq_repo->cancel_retxs(fetch_impl());
459-
}
460-
461486
void dl_harq_process_handle::save_grant_params(const dl_harq_sched_context& ctx, const pdsch_information& pdsch)
462487
{
463488
srsran_assert(pdsch.codewords.size() == 1, "Only one codeword supported");
@@ -511,11 +536,6 @@ int ul_harq_process_handle::ul_crc_info(bool ack)
511536
return ack ? (int)h.prev_tx_params.tbs_bytes : 0;
512537
}
513538

514-
void ul_harq_process_handle::cancel_retxs()
515-
{
516-
harq_repo->cancel_retxs(fetch_impl());
517-
}
518-
519539
void ul_harq_process_handle::save_grant_params(const ul_harq_sched_context& ctx, const pusch_information& pusch)
520540
{
521541
ul_harq_process_impl& impl = fetch_impl();

lib/scheduler/ue_scheduling/cell_harq_manager.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ class base_harq_process_handle
193193
unsigned nof_retxs() const { return fetch_impl().nof_retxs; }
194194
bool ndi() const { return fetch_impl().ndi; }
195195

196+
/// \brief Cancels any retransmissions for this HARQ process.
197+
/// If the HARQ process has a pending retransmission, it is reset. If the ACK/CRC info has not been received yet, the
198+
/// HARQ process waits for it to arrive before being reset.
199+
void cancel_retxs();
200+
196201
bool operator==(const base_harq_process_handle& other) const
197202
{
198203
return harq_repo == other.harq_repo and harq_ref_idx == other.harq_ref_idx;
@@ -255,6 +260,8 @@ class dl_harq_process_handle : public harq_utils::base_harq_process_handle<true>
255260
using base_type::ndi;
256261
using base_type::nof_retxs;
257262

263+
using base_type::cancel_retxs;
264+
258265
[[nodiscard]] bool new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
259266

260267
/// \brief Update the state of the DL HARQ process waiting for an HARQ-ACK.
@@ -265,8 +272,6 @@ class dl_harq_process_handle : public harq_utils::base_harq_process_handle<true>
265272

266273
void increment_pucch_counter();
267274

268-
void cancel_retxs();
269-
270275
/// \brief Stores grant parameters that are associated with the HARQ process (e.g. DCI format, PRBs, MCS) so that
271276
/// they can be later fetched and optionally reused.
272277
void save_grant_params(const dl_harq_sched_context& ctx, const pdsch_information& pdsch);
@@ -296,14 +301,14 @@ class ul_harq_process_handle : public harq_utils::base_harq_process_handle<false
296301
using base_type::ndi;
297302
using base_type::nof_retxs;
298303

304+
using base_type::cancel_retxs;
305+
299306
[[nodiscard]] bool new_retx(slot_point pusch_slot);
300307

301308
/// Update UL HARQ state given the received CRC indication.
302309
/// \return Transport Block size of the HARQ whose state was updated.
303310
int ul_crc_info(bool ack);
304311

305-
void cancel_retxs();
306-
307312
/// \brief Stores grant parameters that are associated with the HARQ process (e.g. DCI format, PRBs, MCS) so that
308313
/// they can be later fetched and optionally reused.
309314
void save_grant_params(const ul_harq_sched_context& ctx, const pusch_information& pdsch);

0 commit comments

Comments
 (0)