From 9e4631ee245fe00421c9790126b3c6cd9f531d45 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 14 Oct 2021 11:45:37 +0100 Subject: [PATCH] Added NR specific config struct for RLC AM. Added status prohibit timer. --- .../srsran/interfaces/rlc_interface_types.h | 8 ++ lib/include/srsran/rlc/rlc_am_nr.h | 11 ++- lib/src/rlc/rlc_am_nr.cc | 96 ++++++++++--------- lib/test/rlc/rlc_am_nr_test.cc | 4 +- 4 files changed, 69 insertions(+), 50 deletions(-) diff --git a/lib/include/srsran/interfaces/rlc_interface_types.h b/lib/include/srsran/interfaces/rlc_interface_types.h index dbef7b071..eb9cd11cf 100644 --- a/lib/include/srsran/interfaces/rlc_interface_types.h +++ b/lib/include/srsran/interfaces/rlc_interface_types.h @@ -219,6 +219,14 @@ public: rlc_cnfg.am.t_poll_retx = 5; return rlc_cnfg; } + static rlc_config_t default_rlc_am_nr_config() + { + rlc_config_t rlc_cnfg = {}; + rlc_cnfg.rat = srsran_rat_t::nr; + rlc_cnfg.rlc_mode = rlc_mode_t::am; + rlc_cnfg.am_nr.t_status_prohibit = 8; + return rlc_cnfg; + } static rlc_config_t default_rlc_um_nr_config(uint32_t sn_size = 6) { rlc_config_t cnfg = {}; diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index 0969f0e67..35bb108c0 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -115,6 +115,9 @@ public: void handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rlc_am_nr_pdu_header_t& header); bool inside_rx_window(uint32_t sn); + // Timers + void timer_expired(uint32_t timeout_id); + // Helpers void debug_state(); @@ -129,11 +132,17 @@ private: // Mutexes std::mutex mutex; + /**************************************************************************** + * Rx timers + * Ref: 3GPP TS 38.322 v10.0.0 Section 7.3 + ***************************************************************************/ + srsran::timer_handler::unique_timer status_prohibit_timer; + /**************************************************************************** * Configurable parameters * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 ***************************************************************************/ - rlc_am_config_t cfg = {}; + rlc_am_nr_config_t cfg = {}; /**************************************************************************** * State Variables diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index f7b5511c4..c746d17a6 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -33,11 +33,7 @@ namespace srsran { /*************************************************************************** * Tx subclass implementation ***************************************************************************/ -rlc_am_nr_tx::rlc_am_nr_tx(rlc_am* parent_) : parent(parent_), rlc_am_base_tx(&parent_->logger) -{ - parent->logger.debug("Initializing RLC AM NR TX: Tx_Next: %d", - st.tx_next); // Temporarly silence unused variable warning -} +rlc_am_nr_tx::rlc_am_nr_tx(rlc_am* parent_) : parent(parent_), rlc_am_base_tx(&parent_->logger) {} bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) { @@ -63,7 +59,8 @@ bool rlc_am_nr_tx::configure(const rlc_config_t& cfg_) bool rlc_am_nr_tx::has_data() { - return true; + return do_status() || // if we have a status PDU to transmit + tx_sdu_queue.get_n_sdus() != 1; // or if there is a SDU queued up for transmission } uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) @@ -194,7 +191,7 @@ void rlc_am_nr_tx::get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) // Bytes needed for status report if (do_status() /* && not TODO status_prohibit_timer*/) { - n_bytes += parent->rx->get_status_pdu_length(); + n_bytes += rx->get_status_pdu_length(); logger->debug("%s Buffer state - total status report: %d bytes", rb_name, n_bytes); } @@ -237,14 +234,21 @@ void rlc_am_nr_tx::stop() {} * Rx subclass implementation ***************************************************************************/ rlc_am_nr_rx::rlc_am_nr_rx(rlc_am* parent_) : - parent(parent_), pool(byte_buffer_pool::get_instance()), rlc_am_base_rx(parent_, &parent_->logger) -{ - parent->logger.debug("Initializing RLC AM NR RX"); // Temporarly silence unused variable warning -} + parent(parent_), + pool(byte_buffer_pool::get_instance()), + status_prohibit_timer(parent->timers->get_unique_timer()), + rlc_am_base_rx(parent_, &parent_->logger) +{} bool rlc_am_nr_rx::configure(const rlc_config_t& cfg_) { - cfg = cfg_.am; + cfg = cfg_.am_nr; + + // configure timers + if (cfg.t_status_prohibit > 0) { + status_prohibit_timer.set(static_cast(cfg.t_status_prohibit), + [this](uint32_t timerid) { timer_expired(timerid); }); + } return true; } @@ -260,26 +264,12 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes) { // Get AMD PDU Header rlc_am_nr_pdu_header_t header = {}; - rlc_am_nr_read_data_pdu_header(payload, nof_bytes, rlc_am_nr_sn_size_t::size12bits, &header); - - // TODO - // if (header.rf != 0) { - // handle_data_pdu_segment(payload, payload_len, header); TODO - //} else { - handle_data_pdu_full(payload, nof_bytes, header); - //} -} - -void rlc_am_nr_rx::handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rlc_am_nr_pdu_header_t& header) -{ - std::map::iterator it; + uint32_t hdr_len = rlc_am_nr_read_data_pdu_header(payload, nof_bytes, rlc_am_nr_sn_size_t::size12bits, &header); logger->info(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", parent->rb_name, header.sn, nof_bytes); log_rlc_am_nr_pdu_header_to_string(logger->debug, header); - // sanity check for segments not exceeding PDU length - // TODO - + // Check wether SDU is within Rx Window if (!inside_rx_window(header.sn)) { logger->info("%s SN=%d outside rx window [%d:%d] - discarding", parent->rb_name, @@ -314,8 +304,8 @@ void rlc_am_nr_rx::handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rl rx_pdu.buf->get_tailroom()); return; } - memcpy(rx_pdu.buf->msg, payload, nof_bytes); - rx_pdu.buf->N_bytes = nof_bytes; + memcpy(rx_pdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header + rx_pdu.buf->N_bytes = nof_bytes - hdr_len; rx_pdu.header = header; // Check poll bit @@ -324,21 +314,6 @@ void rlc_am_nr_rx::handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rl do_status = true; } - // Update Rx_Next_Highest - if (RX_MOD_BASE_NR(header.sn) >= RX_MOD_BASE_NR(rx_next_highest)) { - rx_next_highest = (header.sn + 1) % MOD; - } - - // Update RX_Highest_Status - if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) { - rx_highest_status = (header.sn + 1) % MOD; - } - - // Update RX_Next (FIXME should only be updated if all segments are received) - if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) { - rx_next = header.sn + 1 % MOD; - } - // Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3) // TODO @@ -355,6 +330,21 @@ void rlc_am_nr_rx::handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rl break; } } + + // Update Rx_Next_Highest + if (RX_MOD_BASE_NR(header.sn) >= RX_MOD_BASE_NR(rx_next_highest)) { + rx_next_highest = (header.sn + 1) % MOD; + } + + // Update RX_Highest_Status + if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) { + rx_highest_status = (header.sn + 1) % MOD; + } + + // Update RX_Next (FIXME should only be updated if all segments are received) + if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) { + rx_next = header.sn + 1 % MOD; + } } bool rlc_am_nr_rx::inside_rx_window(uint32_t sn) @@ -394,7 +384,9 @@ uint32_t rlc_am_nr_rx::get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t m // TODO i = (i + 1) % MOD; } - // + if (max_len != UINT32_MAX) { + status_prohibit_timer.run(); // UINT32_MAX is used just to querry the status PDU length + } return tmp_buf.N_bytes; } @@ -406,7 +398,17 @@ uint32_t rlc_am_nr_rx::get_status_pdu_length() bool rlc_am_nr_rx::get_do_status() { - return do_status.load(std::memory_order_relaxed); + return do_status.load(std::memory_order_relaxed) && not status_prohibit_timer.is_running(); +} + +void rlc_am_nr_rx::timer_expired(uint32_t timeout_id) +{ + std::unique_lock lock(mutex); + if (status_prohibit_timer.is_valid() && status_prohibit_timer.id() == timeout_id) { + logger->debug("%s Status prohibit timer expired after %dms", parent->rb_name, status_prohibit_timer.duration()); + } + + lock.unlock(); } /* diff --git a/lib/test/rlc/rlc_am_nr_test.cc b/lib/test/rlc/rlc_am_nr_test.cc index e4c81002d..47e91fbd0 100644 --- a/lib/test/rlc/rlc_am_nr_test.cc +++ b/lib/test/rlc/rlc_am_nr_test.cc @@ -63,11 +63,11 @@ int basic_test() // before configuring entity TESTASSERT(0 == rlc1.get_buffer_state()); - if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) { + if (not rlc1.configure(rlc_config_t::default_rlc_am_nr_config())) { return -1; } - if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) { + if (not rlc2.configure(rlc_config_t::default_rlc_am_nr_config())) { return -1; }