diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index a49b86a1d..9102b4260 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -33,7 +33,8 @@ const static uint32_t max_tx_queue_size = 256; ***************************************************************************/ 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_) { @@ -1364,7 +1365,8 @@ rlc_am_nr_rx::rlc_am_nr_rx(rlc_am* parent_) : status_prohibit_timer(parent->timers->get_unique_timer()), reassembly_timer(parent->timers->get_unique_timer()), rlc_am_base_rx(parent_, parent_->logger) -{} +{ +} bool rlc_am_nr_rx::configure(const rlc_config_t& cfg_) { @@ -1814,7 +1816,7 @@ uint32_t rlc_am_nr_rx::get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t m if (max_len != UINT32_MAX) { // UINT32_MAX is used just to query the status PDU length - if (status_prohibit_timer.is_valid()) { + if (status_prohibit_timer.is_valid() && cfg.t_status_prohibit != 0) { status_prohibit_timer.run(); } do_status = false; @@ -1832,7 +1834,11 @@ 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) && not status_prohibit_timer.is_running(); + if (cfg.t_status_prohibit != 0) { + return do_status.load(std::memory_order_relaxed) && not status_prohibit_timer.is_running(); + } else { + return do_status.load(std::memory_order_relaxed); + } } void rlc_am_nr_rx::timer_expired(uint32_t timeout_id) diff --git a/lib/test/rlc/rlc_am_nr_test.cc b/lib/test/rlc/rlc_am_nr_test.cc index 81f31932a..dc86bd59f 100644 --- a/lib/test/rlc/rlc_am_nr_test.cc +++ b/lib/test/rlc/rlc_am_nr_test.cc @@ -3287,6 +3287,76 @@ int lost_status_and_advanced_rx_window(rlc_am_nr_sn_size_t sn_size) return SRSRAN_SUCCESS; } +// If we lose the status report +int do_status_0ms_status_prohibit(rlc_am_nr_sn_size_t sn_size) +{ + rlc_am_tester tester(true, nullptr); + timer_handler timers(8); + byte_buffer_t pdu_bufs[NBUFS]; + + auto& test_logger = srslog::fetch_basic_logger("TESTER "); + test_delimit_logger delimiter("Do status 0ms status prohibit ({} bit SN)", to_number(sn_size)); + rlc_am rlc1(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers); + rlc_am rlc2(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers); + + rlc_am_nr_tx* tx1 = dynamic_cast(rlc1.get_tx()); + rlc_am_nr_rx* rx1 = dynamic_cast(rlc1.get_rx()); + rlc_am_nr_tx* tx2 = dynamic_cast(rlc2.get_tx()); + rlc_am_nr_rx* rx2 = dynamic_cast(rlc2.get_rx()); + + auto cfg = rlc_config_t::default_rlc_am_nr_config(to_number(sn_size)); + cfg.am_nr.t_status_prohibit = 0; + if (not rlc1.configure(cfg)) { + return -1; + } + if (not rlc2.configure(cfg)) { + return -1; + } + uint32_t mod_nr = cardinality(cfg.am_nr.tx_sn_field_length); + + // Tx 5 PDUs + constexpr uint32_t payload_size = 3; // Give the SDU the size of 3 bytes + uint32_t header_size = sn_size == rlc_am_nr_sn_size_t::size12bits ? 2 : 3; + for (uint32_t sn = 0; sn < 5; ++sn) { + // Write SDU + unique_byte_buffer_t sdu_buf = srsran::make_byte_buffer(); + sdu_buf->msg[0] = sn; // Write the index into the buffer + sdu_buf->N_bytes = payload_size; // Give each buffer a size of 3 bytes + sdu_buf->md.pdcp_sn = sn; // PDCP SN for notifications + rlc1.write_sdu(std::move(sdu_buf)); + + // Read PDU + unique_byte_buffer_t pdu_buf = srsran::make_byte_buffer(); + pdu_buf->N_bytes = rlc1.read_pdu(pdu_buf->msg, 100); + + // Write PDU into RLC 2 + // We receive all PDUs + rlc2.write_pdu(pdu_buf->msg, pdu_buf->N_bytes); + } + + // Read status PDU + { + TESTASSERT_EQ(0, rlc1.get_buffer_state()); + unique_byte_buffer_t status_buf = srsran::make_byte_buffer(); + status_buf->N_bytes = rlc2.read_pdu(status_buf->msg, 1000); + } + + // Let timers run for t-PollRetransmit expire + { + for (int cnt = 0; cnt < 45; cnt++) { + timers.step_all(); + } + TESTASSERT_EQ(header_size + payload_size, rlc1.get_buffer_state()); + TESTASSERT_EQ(0, rlc2.get_buffer_state()); + unique_byte_buffer_t poll_buf = srsran::make_byte_buffer(); + poll_buf->N_bytes = rlc1.read_pdu(poll_buf->msg, 1000); + rlc2.write_pdu(poll_buf->msg, poll_buf->N_bytes); + TESTASSERT_NEQ(0, rlc2.get_buffer_state()); + } + + return SRSRAN_SUCCESS; +} + int full_rx_window_t_reassembly_expiry(rlc_am_nr_sn_size_t sn_size) { rlc_am_tester tester(false, nullptr);