Skip to content

Commit 22abff4

Browse files
committed
sched: extend harq_manager_test to cover all scenarios previously tested in harq_process_test
1 parent 8f2030d commit 22abff4

File tree

6 files changed

+677
-835
lines changed

6 files changed

+677
-835
lines changed

lib/scheduler/ue_scheduling/cell_harq_manager.cpp

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

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

1314
using namespace srsran;
1415
using namespace harq_utils;
@@ -219,9 +220,12 @@ void cell_harq_repository<IsDl>::set_pending_retx(harq_type& h)
219220
}
220221

221222
template <bool IsDl>
222-
void cell_harq_repository<IsDl>::handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack)
223+
bool cell_harq_repository<IsDl>::handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack)
223224
{
224-
srsran_assert(h.status == harq_state_t::pending_retx, "Attempt of retx in an HARQ that has no pending retx");
225+
if (h.status != harq_state_t::pending_retx) {
226+
logger.warning("ue={} h_id={}: Attempt of retx in a HARQ process that has no pending retx", h.ue_idx, h.h_id);
227+
return false;
228+
}
225229

226230
// Remove HARQ from pending Retx list.
227231
harq_pending_retx_list.pop(&h);
@@ -237,6 +241,7 @@ void cell_harq_repository<IsDl>::handle_new_retx(harq_type& h, slot_point sl_tx,
237241
// Add HARQ to the timeout list.
238242
h.slot_ack_timeout = sl_ack + max_ack_wait_in_slots;
239243
harq_timeout_wheel[h.slot_ack_timeout.to_uint() % harq_timeout_wheel.size()].push_front(&h);
244+
return true;
240245
}
241246

242247
template <bool IsDl>
@@ -367,21 +372,24 @@ cell_harq_manager::new_ul_tx(du_ue_index_t ue_idx, slot_point pusch_slot, unsign
367372
return h;
368373
}
369374

370-
void cell_harq_manager::new_dl_retx(harq_utils::dl_harq_process_impl& h,
375+
bool cell_harq_manager::new_dl_retx(harq_utils::dl_harq_process_impl& h,
371376
slot_point pdsch_slot,
372377
unsigned k1,
373378
uint8_t harq_bit_idx)
374379
{
375-
dl.handle_new_retx(h, pdsch_slot, pdsch_slot + k1);
380+
if (not dl.handle_new_retx(h, pdsch_slot, pdsch_slot + k1)) {
381+
return false;
382+
}
376383
h.harq_bit_idx = harq_bit_idx;
377384
h.pucch_ack_to_receive = 0;
378385
h.chosen_ack = mac_harq_ack_report_status::dtx;
379386
h.last_pucch_snr = std::nullopt;
387+
return true;
380388
}
381389

382-
void cell_harq_manager::new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot)
390+
bool cell_harq_manager::new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot)
383391
{
384-
ul.handle_new_retx(h, pusch_slot, pusch_slot);
392+
return ul.handle_new_retx(h, pusch_slot, pusch_slot);
385393
}
386394

387395
dl_harq_process_impl::status_update cell_harq_manager::dl_ack_info(harq_utils::dl_harq_process_impl& h,
@@ -438,32 +446,91 @@ int cell_harq_manager::ul_crc_info(harq_utils::ul_harq_process_impl& h, bool ack
438446
return ack ? (int)h.prev_tx_params.tbs_bytes : 0;
439447
}
440448

441-
void dl_harq_process_view::new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx)
449+
bool dl_harq_process_view::new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx)
442450
{
443-
cell_harq_mng->new_dl_retx(cell_harq_mng->dl.harqs[harq_ref_idx], pdsch_slot, k1, harq_bit_idx);
451+
return cell_harq_mng->new_dl_retx(fetch_impl(), pdsch_slot, k1, harq_bit_idx);
444452
}
445453

446454
dl_harq_process_view::status_update dl_harq_process_view::dl_ack_info(mac_harq_ack_report_status ack,
447455
std::optional<float> pucch_snr)
448456
{
449-
return cell_harq_mng->dl_ack_info(cell_harq_mng->dl.harqs[harq_ref_idx], ack, pucch_snr);
457+
return cell_harq_mng->dl_ack_info(fetch_impl(), ack, pucch_snr);
450458
}
451459

452460
void dl_harq_process_view::increment_pucch_counter()
453461
{
454-
++cell_harq_mng->dl.harqs[harq_ref_idx].pucch_ack_to_receive;
462+
++fetch_impl().pucch_ack_to_receive;
455463
}
456464

457-
void ul_harq_process_view::new_retx(slot_point pusch_slot)
465+
void dl_harq_process_view::save_grant_params(const dl_harq_sched_context& ctx, const pdsch_information& pdsch)
458466
{
459-
cell_harq_mng->new_ul_retx(cell_harq_mng->ul.harqs[harq_ref_idx], pusch_slot);
467+
srsran_assert(pdsch.codewords.size() == 1, "Only one codeword supported");
468+
dl_harq_process_impl& impl = fetch_impl();
469+
srsran_assert(impl.status == harq_utils::harq_state_t::waiting_ack,
470+
"Setting allocation parameters for DL HARQ process id={} in invalid state",
471+
id());
472+
473+
const pdsch_codeword& cw = pdsch.codewords[0];
474+
dl_harq_process_impl::alloc_params& prev_params = impl.prev_tx_params;
475+
476+
if (impl.nof_retxs == 0) {
477+
prev_params.tbs_bytes = cw.tb_size_bytes;
478+
prev_params.dci_cfg_type = ctx.dci_cfg_type;
479+
prev_params.olla_mcs = ctx.olla_mcs;
480+
prev_params.slice_id = ctx.slice_id;
481+
} else {
482+
srsran_assert(ctx.dci_cfg_type == prev_params.dci_cfg_type,
483+
"DCI format and RNTI type cannot change during DL HARQ retxs");
484+
srsran_assert(prev_params.tbs_bytes == cw.tb_size_bytes,
485+
"TBS cannot change during DL HARQ retxs ({}!={}). Previous MCS={}, RBs={}. New MCS={}, RBs={}",
486+
prev_params.tbs_bytes,
487+
cw.tb_size_bytes,
488+
prev_params.mcs,
489+
prev_params.rbs,
490+
cw.mcs_index,
491+
pdsch.rbs);
492+
}
493+
prev_params.mcs_table = cw.mcs_table;
494+
prev_params.mcs = cw.mcs_index;
495+
prev_params.rbs = pdsch.rbs;
496+
prev_params.nof_symbols = pdsch.symbols.length();
497+
}
498+
499+
bool ul_harq_process_view::new_retx(slot_point pusch_slot)
500+
{
501+
return cell_harq_mng->new_ul_retx(cell_harq_mng->ul.harqs[harq_ref_idx], pusch_slot);
460502
}
461503

462504
int ul_harq_process_view::ul_crc_info(bool ack)
463505
{
464506
return cell_harq_mng->ul_crc_info(cell_harq_mng->ul.harqs[harq_ref_idx], ack);
465507
}
466508

509+
void ul_harq_process_view::save_grant_params(const ul_harq_sched_context& ctx, const pusch_information& pusch)
510+
{
511+
ul_harq_process_impl& impl = fetch_impl();
512+
srsran_assert(impl.status == harq_utils::harq_state_t::waiting_ack,
513+
"Setting allocation parameters for DL HARQ process id={} in invalid state",
514+
id());
515+
516+
ul_harq_process_impl::alloc_params& prev_tx_params = impl.prev_tx_params;
517+
518+
if (impl.nof_retxs == 0) {
519+
prev_tx_params.dci_cfg_type = ctx.dci_cfg_type;
520+
prev_tx_params.olla_mcs = ctx.olla_mcs;
521+
prev_tx_params.tbs_bytes = pusch.tb_size_bytes;
522+
prev_tx_params.slice_id = ctx.slice_id;
523+
} else {
524+
srsran_assert(ctx.dci_cfg_type == prev_tx_params.dci_cfg_type,
525+
"DCI format and RNTI type cannot change during HARQ retxs");
526+
srsran_assert(prev_tx_params.tbs_bytes == pusch.tb_size_bytes, "TBS cannot change during HARQ retxs");
527+
}
528+
prev_tx_params.mcs_table = pusch.mcs_table;
529+
prev_tx_params.mcs = pusch.mcs_index;
530+
prev_tx_params.rbs = pusch.rbs;
531+
prev_tx_params.nof_symbols = pusch.symbols.length();
532+
}
533+
467534
// UE HARQ entity.
468535

469536
unique_ue_harq_entity::unique_ue_harq_entity(unique_ue_harq_entity&& other) noexcept :

lib/scheduler/ue_scheduling/cell_harq_manager.h

Lines changed: 85 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#pragma once
1212

13+
#include "../slicing/ran_slice_id.h"
1314
#include "srsran/adt/intrusive_list.h"
1415
#include "srsran/adt/optional.h"
1516
#include "srsran/ran/csi_report/csi_report_data.h"
@@ -24,6 +25,9 @@
2425

2526
namespace srsran {
2627

28+
struct pdsch_information;
29+
struct pusch_information;
30+
2731
class unique_ue_harq_entity;
2832

2933
/// \brief Notifier of HARQ process timeouts.
@@ -79,6 +83,8 @@ struct dl_harq_process_impl : public base_harq_process {
7983
pdsch_mcs_table mcs_table;
8084
sch_mcs_index mcs;
8185
unsigned tbs_bytes;
86+
/// RAN slice identifier.
87+
std::optional<ran_slice_id_t> slice_id;
8288
/// \brief MCS originally suggested by the OLLA. It might differ from the actual MCS used.
8389
std::optional<sch_mcs_index> olla_mcs;
8490
};
@@ -99,13 +105,14 @@ struct dl_harq_process_impl : public base_harq_process {
99105
struct ul_harq_process_impl : public base_harq_process {
100106
/// \brief Parameters relative to the last allocated PUSCH PDU for this HARQ process.
101107
struct alloc_params {
102-
dci_ul_rnti_config_type dci_cfg_type;
103-
vrb_alloc rbs;
104-
pusch_mcs_table mcs_table;
105-
sch_mcs_index mcs;
106-
unsigned tbs_bytes;
107-
unsigned nof_symbols;
108-
std::optional<sch_mcs_index> olla_mcs;
108+
dci_ul_rnti_config_type dci_cfg_type;
109+
vrb_alloc rbs;
110+
pusch_mcs_table mcs_table;
111+
sch_mcs_index mcs;
112+
unsigned tbs_bytes;
113+
unsigned nof_symbols;
114+
std::optional<ran_slice_id_t> slice_id;
115+
std::optional<sch_mcs_index> olla_mcs;
109116
};
110117

111118
/// Parameters used for the last Tx of this HARQ process.
@@ -139,21 +146,41 @@ struct cell_harq_repository {
139146

140147
unsigned get_harq_ref_idx(const harq_type& h) const;
141148

142-
void slot_indication(slot_point sl_tx);
143-
void handle_harq_ack_timeout(harq_type& h, slot_point sl_tx);
144-
harq_type* alloc_harq(du_ue_index_t ue_idx, slot_point sl_tx, slot_point sl_ack, unsigned max_nof_harq_retxs);
145-
void dealloc_harq(harq_type& h);
146-
void handle_ack(harq_type& h, bool ack);
147-
void set_pending_retx(harq_type& h);
148-
void handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack);
149-
void reserve_ue_harqs(du_ue_index_t ue_idx, unsigned nof_harqs);
150-
void destroy_ue_harqs(du_ue_index_t ue_idx);
151-
void cancel_retxs(harq_type& h);
152-
unsigned find_ue_harq_in_state(du_ue_index_t ue_idx, harq_utils::harq_state_t state) const;
149+
void slot_indication(slot_point sl_tx);
150+
void handle_harq_ack_timeout(harq_type& h, slot_point sl_tx);
151+
harq_type* alloc_harq(du_ue_index_t ue_idx, slot_point sl_tx, slot_point sl_ack, unsigned max_nof_harq_retxs);
152+
void dealloc_harq(harq_type& h);
153+
void handle_ack(harq_type& h, bool ack);
154+
void set_pending_retx(harq_type& h);
155+
[[nodiscard]] bool handle_new_retx(harq_type& h, slot_point sl_tx, slot_point sl_ack);
156+
void reserve_ue_harqs(du_ue_index_t ue_idx, unsigned nof_harqs);
157+
void destroy_ue_harqs(du_ue_index_t ue_idx);
158+
void cancel_retxs(harq_type& h);
159+
unsigned find_ue_harq_in_state(du_ue_index_t ue_idx, harq_utils::harq_state_t state) const;
153160
};
154161

155162
} // namespace harq_utils
156163

164+
/// \brief Context of the scheduler during the current PDSCH allocation.
165+
struct dl_harq_sched_context {
166+
/// DCI format used to signal the PDSCH allocation.
167+
dci_dl_rnti_config_type dci_cfg_type;
168+
/// MCS suggested by the OLLA.
169+
std::optional<sch_mcs_index> olla_mcs;
170+
/// RAN slice identifier of the slice to which PDSCH belongs to.
171+
std::optional<ran_slice_id_t> slice_id;
172+
};
173+
174+
/// \brief Context of the scheduler during the current PUSCH allocation.
175+
struct ul_harq_sched_context {
176+
/// DCI format used to signal the PUSCH allocation.
177+
dci_ul_rnti_config_type dci_cfg_type;
178+
/// MCS suggested by the OLLA.
179+
std::optional<sch_mcs_index> olla_mcs;
180+
/// RAN slice identifier of the slice to which PUSCH belongs to.
181+
std::optional<ran_slice_id_t> slice_id;
182+
};
183+
157184
class cell_harq_manager
158185
{
159186
public:
@@ -206,10 +233,11 @@ class cell_harq_manager
206233
harq_utils::ul_harq_process_impl* new_ul_tx(du_ue_index_t ue_idx, slot_point pusch_slot, unsigned max_harq_nof_retxs);
207234

208235
/// \brief Called on a new retx of a DL HARQ process.
209-
void new_dl_retx(harq_utils::dl_harq_process_impl& h, slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
236+
[[nodiscard]] bool
237+
new_dl_retx(harq_utils::dl_harq_process_impl& h, slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
210238

211239
/// \brief Called on a new retx of a UL HARQ process.
212-
void new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot);
240+
[[nodiscard]] bool new_ul_retx(harq_utils::ul_harq_process_impl& h, slot_point pusch_slot);
213241

214242
/// Updates a DL HARQ process given the received HARQ-ACK info.
215243
harq_utils::dl_harq_process_impl::status_update
@@ -241,18 +269,15 @@ class dl_harq_process_view
241269
"Empty HARQ process created");
242270
}
243271

244-
harq_id_t id() const { return cell_harq_mng->dl.harqs[harq_ref_idx].h_id; }
245-
246-
bool is_waiting_ack() const
272+
harq_id_t id() const { return fetch_impl().h_id; }
273+
bool is_waiting_ack() const { return fetch_impl().status == harq_utils::harq_state_t::waiting_ack; }
274+
bool has_pending_retx() const { return fetch_impl().status == harq_utils::harq_state_t::pending_retx; }
275+
bool empty() const
247276
{
248-
return cell_harq_mng->dl.harqs[harq_ref_idx].status == harq_utils::harq_state_t::waiting_ack;
249-
}
250-
bool has_pending_retx() const
251-
{
252-
return cell_harq_mng->dl.harqs[harq_ref_idx].status == harq_utils::harq_state_t::pending_retx;
277+
return harq_ref_idx == cell_harq_manager::INVALID_HARQ or fetch_impl().status == harq_utils::harq_state_t::empty;
253278
}
254279

255-
void new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
280+
[[nodiscard]] bool new_retx(slot_point pdsch_slot, unsigned k1, uint8_t harq_bit_idx);
256281

257282
/// \brief Update the state of the DL HARQ process waiting for an HARQ-ACK.
258283
/// \param[in] ack HARQ-ACK status received.
@@ -262,7 +287,17 @@ class dl_harq_process_view
262287

263288
void increment_pucch_counter();
264289

265-
const grant_params& get_grant_params() const { return cell_harq_mng->dl.harqs[harq_ref_idx].prev_tx_params; }
290+
/// \brief Stores grant parameters that are associated with the HARQ process (e.g. DCI format, PRBs, MCS) so that
291+
/// they can be later fetched and optionally reused.
292+
void save_grant_params(const dl_harq_sched_context& ctx, const pdsch_information& pdsch);
293+
294+
slot_point pdsch_slot() const { return fetch_impl().slot_tx; }
295+
slot_point uci_slot() const { return fetch_impl().slot_ack; }
296+
unsigned max_nof_retxs() const { return fetch_impl().max_nof_harq_retxs; }
297+
unsigned nof_retxs() const { return fetch_impl().nof_retxs; }
298+
bool ndi() const { return fetch_impl().ndi; }
299+
300+
const grant_params& get_grant_params() const { return fetch_impl().prev_tx_params; }
266301

267302
bool operator==(const dl_harq_process_view& other) const
268303
{
@@ -271,6 +306,9 @@ class dl_harq_process_view
271306
bool operator!=(const dl_harq_process_view& other) const { return !(*this == other); }
272307

273308
private:
309+
harq_utils::dl_harq_process_impl& fetch_impl() { return cell_harq_mng->dl.harqs[harq_ref_idx]; }
310+
const harq_utils::dl_harq_process_impl& fetch_impl() const { return cell_harq_mng->dl.harqs[harq_ref_idx]; }
311+
274312
cell_harq_manager* cell_harq_mng = nullptr;
275313
unsigned harq_ref_idx = cell_harq_manager::INVALID_HARQ;
276314
};
@@ -281,34 +319,39 @@ class ul_harq_process_view
281319
ul_harq_process_view(cell_harq_manager& cell_harq_mng_, unsigned h_ref_idx) :
282320
cell_harq_mng(&cell_harq_mng_), harq_ref_idx(h_ref_idx)
283321
{
284-
srsran_sanity_check(cell_harq_mng->ul.harqs[harq_ref_idx].status != harq_utils::harq_state_t::empty,
285-
"Empty HARQ process created");
322+
srsran_sanity_check(fetch_impl().status != harq_utils::harq_state_t::empty, "Empty HARQ process created");
286323
}
287324

288-
harq_id_t id() const { return cell_harq_mng->ul.harqs[harq_ref_idx].h_id; }
325+
harq_id_t id() const { return fetch_impl().h_id; }
289326

290-
bool is_waiting_ack() const
291-
{
292-
return cell_harq_mng->ul.harqs[harq_ref_idx].status == harq_utils::harq_state_t::waiting_ack;
293-
}
294-
bool has_pending_retx() const
295-
{
296-
return cell_harq_mng->ul.harqs[harq_ref_idx].status == harq_utils::harq_state_t::pending_retx;
297-
}
327+
bool is_waiting_ack() const { return fetch_impl().status == harq_utils::harq_state_t::waiting_ack; }
328+
bool has_pending_retx() const { return fetch_impl().status == harq_utils::harq_state_t::pending_retx; }
298329

299-
void new_retx(slot_point pusch_slot);
330+
[[nodiscard]] bool new_retx(slot_point pusch_slot);
300331

301332
/// Update UL HARQ state given the received CRC indication.
302333
/// \return Transport Block size of the HARQ whose state was updated.
303334
int ul_crc_info(bool ack);
304335

336+
/// \brief Stores grant parameters that are associated with the HARQ process (e.g. DCI format, PRBs, MCS) so that
337+
/// they can be later fetched and optionally reused.
338+
void save_grant_params(const ul_harq_sched_context& ctx, const pusch_information& pdsch);
339+
340+
slot_point pusch_slot() const { return fetch_impl().slot_tx; }
341+
unsigned max_nof_retxs() const { return fetch_impl().max_nof_harq_retxs; }
342+
unsigned nof_retxs() const { return fetch_impl().nof_retxs; }
343+
bool ndi() const { return fetch_impl().ndi; }
344+
305345
bool operator==(const ul_harq_process_view& other) const
306346
{
307347
return cell_harq_mng == other.cell_harq_mng and harq_ref_idx == other.harq_ref_idx;
308348
}
309349
bool operator!=(const ul_harq_process_view& other) const { return !(*this == other); }
310350

311351
private:
352+
harq_utils::ul_harq_process_impl& fetch_impl() { return cell_harq_mng->ul.harqs[harq_ref_idx]; }
353+
const harq_utils::ul_harq_process_impl& fetch_impl() const { return cell_harq_mng->ul.harqs[harq_ref_idx]; }
354+
312355
cell_harq_manager* cell_harq_mng = nullptr;
313356
unsigned harq_ref_idx = cell_harq_manager::INVALID_HARQ;
314357
};

tests/unittests/scheduler/ue_scheduling/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
add_executable(ue_scheduler_test
1010
logical_channel_test.cpp
1111
harq_manager_test.cpp
12-
harq_entity_test.cpp
1312
harq_process_test.cpp
1413
fallback_scheduler_test.cpp
1514
ue_cell_test.cpp
@@ -28,5 +27,4 @@ target_link_libraries(ue_scheduler_test
2827
sched_config
2928
gtest
3029
gtest_main)
31-
gtest_discover_tests(ue_scheduler_test)
3230
add_test(ue_scheduler_test ue_scheduler_test)

0 commit comments

Comments
 (0)