Skip to content

Commit 6ed8a6b

Browse files
committed
sched: extend unit tests for new harq_manager class
1 parent 964ca28 commit 6ed8a6b

File tree

3 files changed

+262
-31
lines changed

3 files changed

+262
-31
lines changed

lib/scheduler/ue_scheduling/cell_harq_manager.cpp

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
using namespace srsran;
1414
using namespace harq_utils;
1515

16+
namespace {
17+
18+
class noop_harq_timeout_notifier : public harq_timeout_notifier
19+
{
20+
public:
21+
void on_harq_timeout(du_ue_index_t ue_idx, bool is_dl, bool ack) override
22+
{ /* do nothing */
23+
}
24+
};
25+
26+
} // namespace
27+
1628
template <bool IsDl>
1729
cell_harq_repository<IsDl>::cell_harq_repository(unsigned max_ues,
1830
unsigned max_ack_wait_timeout,
@@ -30,10 +42,11 @@ cell_harq_repository<IsDl>::cell_harq_repository(unsigned max_ues,
3042
ues.resize(max_ues);
3143
for (unsigned i = 0; i != max_ues; i++) {
3244
ues[i].free_harq_ids.reserve(MAX_NOF_HARQS);
33-
ues[i].harqs.resize(MAX_NOF_HARQS, INVALID_HARQ_REF_INDEX);
45+
ues[i].harqs.reserve(MAX_NOF_HARQS);
3446
}
3547

36-
const unsigned RING_SIZE = 40; // TODO: use function to define this value.
48+
const unsigned RING_SIZE = 320; // TODO: use function to define this value. It must account the timeout arg and k
49+
// values
3750
harq_timeout_wheel.resize(RING_SIZE);
3851
}
3952

@@ -42,8 +55,8 @@ void cell_harq_repository<IsDl>::slot_indication(slot_point sl_tx)
4255
{
4356
// Handle HARQs that timed out.
4457
auto& harqs_timing_out = harq_timeout_wheel[sl_tx.to_uint() % harq_timeout_wheel.size()];
45-
for (harq_type& h : harqs_timing_out) {
46-
handle_harq_ack_timeout(h, sl_tx);
58+
while (not harqs_timing_out.empty()) {
59+
handle_harq_ack_timeout(harqs_timing_out.front(), sl_tx);
4760
}
4861
}
4962

@@ -205,13 +218,36 @@ void cell_harq_repository<IsDl>::set_pending_retx(harq_type& h)
205218
h.status = harq_state_t::pending_retx;
206219
}
207220

221+
template <bool IsDl>
222+
void cell_harq_repository<IsDl>::handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack)
223+
{
224+
srsran_assert(h.status == harq_state_t::pending_retx, "Attempt of retx in an HARQ that has no pending retx");
225+
226+
// Remove HARQ from pending Retx list.
227+
harq_pending_retx_list.pop(&h);
228+
229+
h.status = harq_state_t::waiting_ack;
230+
h.slot_tx = sl_tx;
231+
h.slot_ack = sl_ack;
232+
h.ndi = !h.ndi;
233+
h.ack_on_timeout = false;
234+
h.retxs_cancelled = false;
235+
h.nof_retxs++;
236+
237+
// Add HARQ to the timeout list.
238+
h.slot_ack_timeout = sl_ack + max_ack_wait_in_slots;
239+
harq_timeout_wheel[h.slot_ack_timeout.to_uint() % harq_timeout_wheel.size()].push_front(&h);
240+
}
241+
208242
template <bool IsDl>
209243
void cell_harq_repository<IsDl>::reserve_ue_harqs(du_ue_index_t ue_idx, unsigned nof_harqs)
210244
{
245+
ues[ue_idx].harqs.resize(nof_harqs);
211246
ues[ue_idx].free_harq_ids.resize(nof_harqs);
212247
for (unsigned count = 0; count != nof_harqs; count++) {
213248
harq_id_t h_id = to_harq_id(nof_harqs - count - 1);
214249
ues[ue_idx].free_harq_ids[count] = h_id;
250+
ues[ue_idx].harqs[count] = INVALID_HARQ_REF_INDEX;
215251
}
216252
}
217253

@@ -259,7 +295,7 @@ template struct harq_utils::cell_harq_repository<false>;
259295
cell_harq_manager::cell_harq_manager(unsigned max_ues,
260296
std::unique_ptr<harq_timeout_notifier> notifier,
261297
unsigned max_ack_wait_timeout) :
262-
timeout_notifier(std::move(notifier)),
298+
timeout_notifier(notifier != nullptr ? std::move(notifier) : std::make_unique<noop_harq_timeout_notifier>()),
263299
logger(srslog::fetch_basic_logger("SCHED")),
264300
dl(max_ues, max_ack_wait_timeout, *timeout_notifier, logger),
265301
ul(max_ues, max_ack_wait_timeout, *timeout_notifier, logger)
@@ -275,14 +311,15 @@ void cell_harq_manager::slot_indication(slot_point sl_tx)
275311

276312
bool cell_harq_manager::contains(du_ue_index_t ue_idx) const
277313
{
278-
return dl.ues[ue_idx].free_harq_ids.size() != 0;
314+
return ue_idx < dl.ues.size() and dl.ues[ue_idx].free_harq_ids.size() != 0;
279315
}
280316

281317
unique_ue_harq_entity
282318
cell_harq_manager::add_ue(du_ue_index_t ue_idx, rnti_t crnti, unsigned nof_dl_harq_procs, unsigned nof_ul_harq_procs)
283319
{
284-
srsran_assert(nof_dl_harq_procs > 0, "Invalid number of HARQs");
285-
srsran_assert(nof_ul_harq_procs > 0, "Invalid number of HARQs");
320+
srsran_sanity_check(nof_dl_harq_procs > 0, "Invalid number of HARQs");
321+
srsran_sanity_check(nof_ul_harq_procs > 0, "Invalid number of HARQs");
322+
srsran_sanity_check(ue_idx < dl.ues.size(), "Invalid ue_index");
286323
srsran_assert(not contains(ue_idx), "Creating UE with duplicate ue_index");
287324
dl.reserve_ue_harqs(ue_idx, nof_dl_harq_procs);
288325
ul.reserve_ue_harqs(ue_idx, nof_ul_harq_procs);
@@ -330,6 +367,23 @@ cell_harq_manager::new_ul_tx(du_ue_index_t ue_idx, slot_point pusch_slot, unsign
330367
return h;
331368
}
332369

370+
void cell_harq_manager::new_dl_retx(harq_utils::dl_harq_process_impl& h,
371+
slot_point pdsch_slot,
372+
unsigned k1,
373+
uint8_t harq_bit_idx)
374+
{
375+
dl.handle_new_retx(h, pdsch_slot, pdsch_slot + k1);
376+
h.harq_bit_idx = harq_bit_idx;
377+
h.pucch_ack_to_receive = 0;
378+
h.chosen_ack = mac_harq_ack_report_status::dtx;
379+
h.last_pucch_snr = std::nullopt;
380+
}
381+
382+
void cell_harq_manager::new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot)
383+
{
384+
ul.handle_new_retx(h, pusch_slot, pusch_slot);
385+
}
386+
333387
dl_harq_process_impl::status_update cell_harq_manager::dl_ack_info(harq_utils::dl_harq_process_impl& h,
334388
mac_harq_ack_report_status ack,
335389
std::optional<float> pucch_snr)
@@ -384,12 +438,22 @@ int cell_harq_manager::ul_crc_info(harq_utils::ul_harq_process_impl& h, bool ack
384438
return ack ? (int)h.prev_tx_params.tbs_bytes : 0;
385439
}
386440

441+
void dl_harq_process_view::new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx)
442+
{
443+
cell_harq_mng->new_dl_retx(cell_harq_mng->dl.harqs[harq_ref_idx], pdsch_slot, k1, harq_bit_idx);
444+
}
445+
387446
dl_harq_process_view::status_update dl_harq_process_view::dl_ack_info(mac_harq_ack_report_status ack,
388447
std::optional<float> pucch_snr)
389448
{
390449
return cell_harq_mng->dl_ack_info(cell_harq_mng->dl.harqs[harq_ref_idx], ack, pucch_snr);
391450
}
392451

452+
void ul_harq_process_view::new_retx(slot_point pusch_slot)
453+
{
454+
cell_harq_mng->new_ul_retx(cell_harq_mng->ul.harqs[harq_ref_idx], pusch_slot);
455+
}
456+
393457
int ul_harq_process_view::ul_crc_info(bool ack)
394458
{
395459
return cell_harq_mng->ul_crc_info(cell_harq_mng->ul.harqs[harq_ref_idx], ack);

lib/scheduler/ue_scheduling/cell_harq_manager.h

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ class harq_timeout_notifier
3636
virtual void on_harq_timeout(du_ue_index_t ue_idx, bool is_dl, bool ack) = 0;
3737
};
3838

39-
class noop_harq_timeout_notifier : public harq_timeout_notifier
40-
{
41-
public:
42-
void on_harq_timeout(du_ue_index_t ue_idx, bool is_dl, bool ack) override
43-
{ /* do nothing */
44-
}
45-
};
46-
4739
namespace harq_utils {
4840

4941
const static unsigned INVALID_HARQ_REF_INDEX = std::numeric_limits<unsigned>::max();
@@ -153,6 +145,7 @@ struct cell_harq_repository {
153145
void dealloc_harq(harq_type& h);
154146
void handle_ack(harq_type& h, bool ack);
155147
void set_pending_retx(harq_type& h);
148+
void handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack);
156149
void reserve_ue_harqs(du_ue_index_t ue_idx, unsigned nof_harqs);
157150
void destroy_ue_harqs(du_ue_index_t ue_idx);
158151
void cancel_retxs(harq_type& h);
@@ -168,8 +161,8 @@ class cell_harq_manager
168161
/// (implementation-defined).
169162
constexpr static unsigned DEFAULT_ACK_TIMEOUT_SLOTS = 256U;
170163

171-
cell_harq_manager(unsigned max_ues = MAX_NOF_DU_UES,
172-
std::unique_ptr<harq_timeout_notifier> notifier = std::make_unique<noop_harq_timeout_notifier>(),
164+
cell_harq_manager(unsigned max_ues = MAX_NOF_DU_UES,
165+
std::unique_ptr<harq_timeout_notifier> notifier = nullptr,
173166
unsigned max_ack_wait_timeout = DEFAULT_ACK_TIMEOUT_SLOTS);
174167

175168
/// Update slot, and checks if there are HARQ processes that have reached maxReTx with no ACK
@@ -203,7 +196,7 @@ class cell_harq_manager
203196

204197
void destroy_ue(du_ue_index_t ue_idx);
205198

206-
/// \brief Called on every DL new Tx to allocate an UL HARQ process.
199+
/// \brief Called on every DL new Tx to allocate an DL HARQ process.
207200
harq_utils::dl_harq_process_impl* new_dl_tx(du_ue_index_t ue_idx,
208201
slot_point pdsch_slot,
209202
unsigned k1,
@@ -213,6 +206,12 @@ class cell_harq_manager
213206
/// \brief Called on every UL new Tx to allocate an UL HARQ process.
214207
harq_utils::ul_harq_process_impl* new_ul_tx(du_ue_index_t ue_idx, slot_point pusch_slot, unsigned max_harq_nof_retxs);
215208

209+
/// \brief Called on a new retx of a DL HARQ process.
210+
void new_dl_retx(harq_utils::dl_harq_process_impl& h, slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
211+
212+
/// \brief Called on a new retx of a UL HARQ process.
213+
void new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot);
214+
216215
/// Updates a DL HARQ process given the received HARQ-ACK info.
217216
harq_utils::dl_harq_process_impl::status_update
218217
dl_ack_info(harq_utils::dl_harq_process_impl& h, mac_harq_ack_report_status ack, std::optional<float> pucch_snr);
@@ -243,6 +242,8 @@ class dl_harq_process_view
243242
"Empty HARQ process created");
244243
}
245244

245+
harq_id_t id() const { return cell_harq_mng->dl.harqs[harq_ref_idx].h_id; }
246+
246247
bool is_waiting_ack() const
247248
{
248249
return cell_harq_mng->dl.harqs[harq_ref_idx].status == harq_utils::harq_state_t::waiting_ack;
@@ -252,6 +253,8 @@ class dl_harq_process_view
252253
return cell_harq_mng->dl.harqs[harq_ref_idx].status == harq_utils::harq_state_t::pending_retx;
253254
}
254255

256+
void new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
257+
255258
/// \brief Update the state of the DL HARQ process waiting for an HARQ-ACK.
256259
/// \param[in] ack HARQ-ACK status received.
257260
/// \param[in] pucch_snr SNR of the PUCCH that carried the HARQ-ACK.
@@ -281,6 +284,8 @@ class ul_harq_process_view
281284
"Empty HARQ process created");
282285
}
283286

287+
harq_id_t id() const { return cell_harq_mng->ul.harqs[harq_ref_idx].h_id; }
288+
284289
bool is_waiting_ack() const
285290
{
286291
return cell_harq_mng->ul.harqs[harq_ref_idx].status == harq_utils::harq_state_t::waiting_ack;
@@ -290,6 +295,8 @@ class ul_harq_process_view
290295
return cell_harq_mng->ul.harqs[harq_ref_idx].status == harq_utils::harq_state_t::pending_retx;
291296
}
292297

298+
void new_retx(slot_point pusch_slot);
299+
293300
/// Update UL HARQ state given the received CRC indication.
294301
/// \return Transport Block size of the HARQ whose state was updated.
295302
int ul_crc_info(bool ack);
@@ -320,12 +327,15 @@ class unique_ue_harq_entity
320327
unique_ue_harq_entity& operator=(const unique_ue_harq_entity&) = delete;
321328
unique_ue_harq_entity& operator=(unique_ue_harq_entity&& other) noexcept;
322329

330+
/// Gets the maximum number of HARQ processes a UE can use, which depends on its configuration.
323331
unsigned nof_dl_harqs() const { return get_dl_ue().harqs.size(); }
324332
unsigned nof_ul_harqs() const { return get_ul_ue().harqs.size(); }
325333

334+
/// Checks whether there are free HARQ processes.
326335
bool has_empty_dl_harqs() const { return not get_dl_ue().free_harq_ids.empty(); }
327336
bool has_empty_ul_harqs() const { return not get_ul_ue().free_harq_ids.empty(); }
328337

338+
/// Deallocate UE HARQ entity.
329339
void reset();
330340

331341
std::optional<dl_harq_process_view> dl_harq(harq_id_t h_id)

0 commit comments

Comments
 (0)