@@ -173,13 +173,15 @@ class base_harq_process_handle
173173 using harq_impl_type = std::conditional_t <IsDl, dl_harq_process_impl, ul_harq_process_impl>;
174174
175175public:
176+ base_harq_process_handle () = default ;
176177 base_harq_process_handle (harq_pool& pool_, unsigned harq_ref_idx_) : harq_repo(&pool_), harq_ref_idx(harq_ref_idx_)
177178 {
178179 srsran_sanity_check (harq_ref_idx < harq_repo->harqs .size (), " Invalid HARQ created" );
179180 srsran_sanity_check (harq_repo->harqs [harq_ref_idx].status != harq_utils::harq_state_t ::empty,
180181 " Empty HARQ process created" );
181182 }
182183
184+ rnti_t rnti () const { return fetch_impl ().rnti ; }
183185 harq_id_t id () const { return fetch_impl ().h_id ; }
184186 bool is_waiting_ack () const { return fetch_impl ().status == harq_utils::harq_state_t ::waiting_ack; }
185187 bool has_pending_retx () const { return fetch_impl ().status == harq_utils::harq_state_t ::pending_retx; }
@@ -227,61 +229,6 @@ struct ul_harq_sched_context {
227229 std::optional<ran_slice_id_t > slice_id;
228230};
229231
230- class cell_harq_manager
231- {
232- public:
233- // / \brief Default timeout in slots after which the HARQ process assumes that the CRC/ACK went missing
234- // / (implementation-defined).
235- constexpr static unsigned DEFAULT_ACK_TIMEOUT_SLOTS = 256U ;
236-
237- cell_harq_manager (unsigned max_ues = MAX_NOF_DU_UES,
238- std::unique_ptr<harq_timeout_notifier> notifier = nullptr ,
239- unsigned max_ack_wait_timeout = DEFAULT_ACK_TIMEOUT_SLOTS);
240-
241- // / Update slot, and checks if there are HARQ processes that have reached maxReTx with no ACK
242- void slot_indication (slot_point sl_tx);
243-
244- // / Create new UE HARQ entity.
245- // / \param rnti RNTI of the UE
246- // / \param nof_dl_harq_procs Number of DL HARQ processes that the UE can support. This value is derived based on
247- // / the UE capabilities, and passed to the UE via RRC signalling. See TS38.331, "nrofHARQ-ProcessesForPDSCH".
248- // / Values: {2, 4, 6, 10, 12, 16}.
249- // / \param nof_ul_harq_procs Number of UL HARQ processes that gNB can support. This value is implementation-defined
250- // / and can up to 16 (there are up to 4 bits for HARQ-Id signalling).
251- unique_ue_harq_entity add_ue (du_ue_index_t ue_idx,
252- rnti_t crnti,
253- unsigned nof_dl_harq_procs = MAX_NOF_HARQS,
254- unsigned nof_ul_harq_procs = MAX_NOF_HARQS);
255-
256- // / Checks whether an UE with the provided ue index exists.
257- bool contains (du_ue_index_t ue_idx) const ;
258-
259- private:
260- friend class unique_ue_harq_entity ;
261-
262- void destroy_ue (du_ue_index_t ue_idx);
263-
264- // / \brief Called on every DL new Tx to allocate an DL HARQ process.
265- harq_utils::dl_harq_process_impl* new_dl_tx (du_ue_index_t ue_idx,
266- rnti_t rnti,
267- slot_point pdsch_slot,
268- unsigned k1,
269- unsigned max_harq_nof_retxs,
270- uint8_t harq_bit_idx);
271-
272- // / \brief Called on every UL new Tx to allocate an UL HARQ process.
273- harq_utils::ul_harq_process_impl*
274- new_ul_tx (du_ue_index_t ue_idx, rnti_t rnti, slot_point pusch_slot, unsigned max_harq_nof_retxs);
275-
276- std::unique_ptr<harq_timeout_notifier> timeout_notifier;
277- srslog::basic_logger& logger;
278-
279- slot_point last_sl_tx;
280-
281- harq_utils::cell_harq_repository<true > dl;
282- harq_utils::cell_harq_repository<false > ul;
283- };
284-
285232// / \brief Interface used to fetch and update the status of a DL HARQ process.
286233// / \remark This handle acts like a view to an internal HARQ process. It is not a "unique" type that controls the
287234// / lifetime of a HARQ. Avoid storing and using the same handle across different slots.
@@ -297,10 +244,7 @@ class dl_harq_process_handle : public harq_utils::base_harq_process_handle<true>
297244 using status_update = harq_utils::dl_harq_process_impl::status_update;
298245 using grant_params = harq_utils::dl_harq_process_impl::alloc_params;
299246
300- dl_harq_process_handle (harq_utils::cell_harq_repository<true >& harq_repo_, unsigned h_ref_idx_) :
301- base_type (harq_repo_, h_ref_idx_)
302- {
303- }
247+ using base_type::base_type;
304248
305249 using base_type::empty;
306250 using base_type::has_pending_retx;
@@ -341,7 +285,7 @@ class ul_harq_process_handle : public harq_utils::base_harq_process_handle<false
341285 using base_type = harq_utils::base_harq_process_handle<false >;
342286
343287public:
344- ul_harq_process_handle (harq_pool& harq_repo_, unsigned h_ref_idx) : base_type(harq_repo_, h_ref_idx) {}
288+ using base_type:: base_type;
345289
346290 using base_type::empty;
347291 using base_type::has_pending_retx;
@@ -367,6 +311,124 @@ class ul_harq_process_handle : public harq_utils::base_harq_process_handle<false
367311 slot_point pusch_slot () const { return fetch_impl ().slot_tx ; }
368312};
369313
314+ namespace harq_utils {
315+
316+ template <bool IsDl>
317+ class harq_pending_retx_list_impl
318+ {
319+ using harq_pool = harq_utils::cell_harq_repository<IsDl>;
320+ using harq_impl_type = std::conditional_t <IsDl, harq_utils::dl_harq_process_impl, harq_utils::ul_harq_process_impl>;
321+ using handle_type = std::conditional_t <IsDl, dl_harq_process_handle, ul_harq_process_handle>;
322+
323+ public:
324+ struct iterator {
325+ using value_type = handle_type;
326+ using reference = handle_type;
327+ using pointer = std::optional<value_type>;
328+ using iterator_category = std::forward_iterator_tag;
329+
330+ iterator (harq_pool& pool_, typename intrusive_double_linked_list<harq_impl_type>::iterator it_) :
331+ pool (&pool_), it(it_)
332+ {
333+ }
334+
335+ reference operator ++()
336+ {
337+ ++it;
338+ return value ();
339+ }
340+ reference operator *() { return value (); }
341+ reference value ()
342+ {
343+ return it != pool->harq_pending_retx_list .end () ? handle_type{*pool, get_harq_ref_idx (*it)} : handle_type{};
344+ }
345+
346+ bool operator ==(const iterator& other) const { return pool == other.pool and it == other.it ; }
347+ bool operator !=(const iterator& other) const { return !(*this == other); }
348+
349+ private:
350+ unsigned get_harq_ref_idx (const harq_impl_type& h) { return &h - pool->harqs .data (); }
351+
352+ harq_pool* pool;
353+ typename intrusive_double_linked_list<harq_impl_type>::iterator it;
354+ };
355+
356+ explicit harq_pending_retx_list_impl (harq_pool& pool_) : pool(&pool_) {}
357+
358+ bool empty () const { return pool->harq_pending_retx_list .empty (); }
359+
360+ iterator begin () { return iterator{*pool, pool->harq_pending_retx_list .begin ()}; }
361+ iterator end () { return iterator{*pool, pool->harq_pending_retx_list .end ()}; }
362+
363+ private:
364+ harq_pool* pool;
365+ };
366+
367+ } // namespace harq_utils
368+
369+ using dl_harq_pending_retx_list = harq_utils::harq_pending_retx_list_impl<true >;
370+ using ul_harq_pending_retx_list = harq_utils::harq_pending_retx_list_impl<false >;
371+
372+ // / Manager of all HARQ processes in a given cell.
373+ class cell_harq_manager
374+ {
375+ public:
376+ // / \brief Default timeout in slots after which the HARQ process assumes that the CRC/ACK went missing
377+ // / (implementation-defined).
378+ constexpr static unsigned DEFAULT_ACK_TIMEOUT_SLOTS = 256U ;
379+
380+ cell_harq_manager (unsigned max_ues = MAX_NOF_DU_UES,
381+ std::unique_ptr<harq_timeout_notifier> notifier = nullptr ,
382+ unsigned max_ack_wait_timeout = DEFAULT_ACK_TIMEOUT_SLOTS);
383+
384+ // / Update slot, and checks if there are HARQ processes that have reached maxReTx with no ACK
385+ void slot_indication (slot_point sl_tx);
386+
387+ // / Create new UE HARQ entity.
388+ // / \param rnti RNTI of the UE
389+ // / \param nof_dl_harq_procs Number of DL HARQ processes that the UE can support. This value is derived based on
390+ // / the UE capabilities, and passed to the UE via RRC signalling. See TS38.331, "nrofHARQ-ProcessesForPDSCH".
391+ // / Values: {2, 4, 6, 10, 12, 16}.
392+ // / \param nof_ul_harq_procs Number of UL HARQ processes that gNB can support. This value is implementation-defined
393+ // / and can up to 16 (there are up to 4 bits for HARQ-Id signalling).
394+ unique_ue_harq_entity add_ue (du_ue_index_t ue_idx,
395+ rnti_t crnti,
396+ unsigned nof_dl_harq_procs = MAX_NOF_HARQS,
397+ unsigned nof_ul_harq_procs = MAX_NOF_HARQS);
398+
399+ // / Checks whether an UE with the provided ue index exists.
400+ bool contains (du_ue_index_t ue_idx) const ;
401+
402+ // / Retrieve list of HARQ processes with pending retxs.
403+ dl_harq_pending_retx_list pending_dl_retxs ();
404+ ul_harq_pending_retx_list pending_ul_retxs ();
405+
406+ private:
407+ friend class unique_ue_harq_entity ;
408+
409+ void destroy_ue (du_ue_index_t ue_idx);
410+
411+ // / \brief Called on every DL new Tx to allocate an DL HARQ process.
412+ harq_utils::dl_harq_process_impl* new_dl_tx (du_ue_index_t ue_idx,
413+ rnti_t rnti,
414+ slot_point pdsch_slot,
415+ unsigned k1,
416+ unsigned max_harq_nof_retxs,
417+ uint8_t harq_bit_idx);
418+
419+ // / \brief Called on every UL new Tx to allocate an UL HARQ process.
420+ harq_utils::ul_harq_process_impl*
421+ new_ul_tx (du_ue_index_t ue_idx, rnti_t rnti, slot_point pusch_slot, unsigned max_harq_nof_retxs);
422+
423+ std::unique_ptr<harq_timeout_notifier> timeout_notifier;
424+ srslog::basic_logger& logger;
425+
426+ slot_point last_sl_tx;
427+
428+ harq_utils::cell_harq_repository<true > dl;
429+ harq_utils::cell_harq_repository<false > ul;
430+ };
431+
370432class unique_ue_harq_entity
371433{
372434public:
0 commit comments