diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index 0baadcd68..d64aabc27 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -98,6 +98,7 @@ public: bool sdu_queue_is_full() final; void reestablish() final; + void stop() final; int write_sdu(unique_byte_buffer_t sdu); void empty_queue() final; @@ -125,8 +126,10 @@ public: // Polling uint8_t get_pdu_poll(bool is_retx, uint32_t sdu_bytes); - void stop() final; + // Timers + void timer_expired(uint32_t timeout_id); + // Window helpers bool inside_tx_window(uint32_t sn) const; private: @@ -166,6 +169,12 @@ private: ***************************************************************************/ inline uint32_t tx_window_size() const; + /**************************************************************************** + * TX timers + * Ref: 3GPP TS 38.322 version 16.2.0 Section 7.3 + ***************************************************************************/ + srsran::timer_handler::unique_timer poll_retransmit_timer; + public: // Getters/Setters void set_tx_state(const rlc_am_nr_tx_state_t& st_) { st = st_; } // This should only be used for testing. diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index e05ae4cf2..836feaa03 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -32,7 +32,9 @@ const static uint32_t so_end_of_sdu = 0xFFFF; /*************************************************************************** * Tx subclass implementation ***************************************************************************/ -rlc_am_nr_tx::rlc_am_nr_tx(rlc_am* parent_) : parent(parent_), rlc_am_base_tx(parent_->logger) {} +rlc_am_nr_tx::rlc_am_nr_tx(rlc_am* parent_) : + parent(parent_), rlc_am_base_tx(parent_->logger), poll_retransmit_timer(parent->timers->get_unique_timer()) +{} bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) { @@ -73,6 +75,19 @@ bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) empty_queue_no_lock(); tx_sdu_queue.resize(cfg_.tx_queue_length); + // Check timers are valid + if (not poll_retransmit_timer.is_valid()) { + RlcError("Configuring TX: timers not configured"); + return false; + } + + // Configure t_poll_retransmission timer + if (cfg.t_poll_retx > 0) { + poll_retransmit_timer.set(static_cast(cfg.t_poll_retx), + [this](uint32_t timerid) { timer_expired(timerid); }); + RlcInfo("configured poll retransmission timer. t-pollRetransmission=%d ms", cfg.t_poll_retx); + } + tx_enabled = true; RlcDebug("RLC AM NR configured tx entity."); @@ -1112,6 +1127,17 @@ void rlc_am_nr_tx::empty_queue_no_lock() } void rlc_am_nr_tx::stop() {} +void rlc_am_nr_tx::timer_expired(uint32_t timeout_id) +{ + std::unique_lock lock(mutex); + + // Status Prohibit + if (poll_retransmit_timer.is_valid() && poll_retransmit_timer.id() == timeout_id) { + RlcDebug("Status prohibit timer expired after %dms", poll_retransmit_timer.duration()); + return; + } +} + /* * Window helpers */