diff --git a/lib/include/srsran/rlc/rlc_am_data_structs.h b/lib/include/srsran/rlc/rlc_am_data_structs.h index 3c416cf33..a8515237a 100644 --- a/lib/include/srsran/rlc/rlc_am_data_structs.h +++ b/lib/include/srsran/rlc/rlc_am_data_structs.h @@ -300,6 +300,59 @@ private: uint32_t count = 0; }; +struct rlc_amd_retx_t { + uint32_t sn; + bool is_segment; + uint32_t so_start; + uint32_t so_end; +}; + +template +class pdu_retx_queue +{ +public: + rlc_amd_retx_t& push() + { + assert(not full()); + rlc_amd_retx_t& p = buffer[wpos]; + wpos = (wpos + 1) % WINDOW_SIZE; + return p; + } + + void pop() { rpos = (rpos + 1) % WINDOW_SIZE; } + + rlc_amd_retx_t& front() + { + assert(not empty()); + return buffer[rpos]; + } + + void clear() + { + wpos = 0; + rpos = 0; + } + + bool has_sn(uint32_t sn) const + { + for (size_t i = rpos; i != wpos; i = (i + 1) % WINDOW_SIZE) { + if (buffer[i].sn == sn) { + return true; + } + } + return false; + } + + size_t size() const { return (wpos >= rpos) ? wpos - rpos : WINDOW_SIZE + wpos - rpos; } + bool empty() const { return wpos == rpos; } + bool full() const { return size() == WINDOW_SIZE - 1; } + +private: + std::array buffer; + size_t wpos = 0; + size_t rpos = 0; +}; + } // namespace srsran #endif // SRSRAN_RLC_AM_DATA_STRUCTS_H diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index ce487c1f9..4a1cf9c4b 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -35,51 +35,6 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG -class pdu_retx_queue -{ -public: - rlc_amd_retx_t& push() - { - assert(not full()); - rlc_amd_retx_t& p = buffer[wpos]; - wpos = (wpos + 1) % RLC_AM_WINDOW_SIZE; - return p; - } - - void pop() { rpos = (rpos + 1) % RLC_AM_WINDOW_SIZE; } - - rlc_amd_retx_t& front() - { - assert(not empty()); - return buffer[rpos]; - } - - void clear() - { - wpos = 0; - rpos = 0; - } - - bool has_sn(uint32_t sn) const - { - for (size_t i = rpos; i != wpos; i = (i + 1) % RLC_AM_WINDOW_SIZE) { - if (buffer[i].sn == sn) { - return true; - } - } - return false; - } - - size_t size() const { return (wpos >= rpos) ? wpos - rpos : RLC_AM_WINDOW_SIZE + wpos - rpos; } - bool empty() const { return wpos == rpos; } - bool full() const { return size() == RLC_AM_WINDOW_SIZE - 1; } - -private: - std::array buffer; - size_t wpos = 0; - size_t rpos = 0; -}; - /****************************** * * RLC AM LTE entity @@ -183,7 +138,7 @@ private: // Tx windows rlc_ringbuffer_t, RLC_AM_WINDOW_SIZE> tx_window; - pdu_retx_queue retx_queue; + pdu_retx_queue retx_queue; pdcp_sn_vector_t notify_info_vec; // Mutexes diff --git a/lib/include/srsran/rlc/rlc_am_lte_packing.h b/lib/include/srsran/rlc/rlc_am_lte_packing.h index e9ae3e8d4..dbb6377ef 100644 --- a/lib/include/srsran/rlc/rlc_am_lte_packing.h +++ b/lib/include/srsran/rlc/rlc_am_lte_packing.h @@ -20,13 +20,6 @@ namespace srsran { -struct rlc_amd_retx_t { - uint32_t sn; - bool is_segment; - uint32_t so_start; - uint32_t so_end; -}; - struct rlc_sn_info_t { uint32_t sn; bool is_acked; diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index bac8d4c05..f4a3a1783 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -156,11 +156,6 @@ uint32_t rlc_am_nr_tx::build_status_pdu(byte_buffer_t* payload, uint32_t nof_byt } else if (pdu_len > 0 && nof_bytes >= static_cast(pdu_len)) { logger->debug("Generated Status PDU. Bytes:%d", pdu_len); log_rlc_am_nr_status_pdu_to_string(logger->info, "%s Tx status PDU - %s", &tx_status, rb_name); - // if (cfg.t_status_prohibit > 0 && status_prohibit_timer.is_valid()) { - // re-arm timer - // status_prohibit_timer.run(); - //} - // debug_state(); pdu_len = rlc_am_nr_write_status_pdu(tx_status, rlc_am_nr_sn_size_t::size12bits, payload); } else { logger->info("%s Cannot tx status PDU - %d bytes available, %d bytes required", rb_name, nof_bytes, pdu_len); @@ -170,7 +165,61 @@ uint32_t rlc_am_nr_tx::build_status_pdu(byte_buffer_t* payload, uint32_t nof_byt return payload->N_bytes; } -void rlc_am_nr_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes) {} +void rlc_am_nr_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + if (not tx_enabled) { + return; + } + + rlc_am_nr_status_pdu_t status = {}; + logger->debug(payload, nof_bytes, "%s Rx control PDU", parent->rb_name); + rlc_am_nr_read_status_pdu(payload, nof_bytes, rlc_am_nr_sn_size_t::size12bits, &status); + log_rlc_am_nr_status_pdu_to_string(logger->info, "%s Rx Status PDU: %s", &status, parent->rb_name); + // Local variables for handling Status PDU will be updated with lock + uint32_t ack_sn = status.ack_sn; + uint32_t n_nacks = status.N_nack; + /* + * - if the SN of the corresponding RLC SDU falls within the range + * TX_Next_Ack <= SN < = the highest SN of the AMD PDU among the AMD PDUs submitted to lower layer: + * - consider the RLC SDU or the RLC SDU segment for which a negative acknowledgement was received for + * retransmission. + */ + // Process N_acks + /* + for (uint32_t nack_idx = 0; nack_idx < status.N_nack; nack_idx++) { + if (st.tx_next_ack <= status.nacks[nack_idx].nack_sn && status.nacks[nack_idx].nack_sn <= tx_window.end()) { + uint32_t nack_sn = status.nacks[nack_idx].nack_sn; + if (tx_window.has_sn(nack_sn)) { + auto& pdu = tx_window[nack_sn]; + + // add to retx queue if it's not already there + if (not retx_queue.has_sn(nack_sn)) { + // increment Retx counter and inform upper layers if needed + pdu.retx_count++; + check_sn_reached_max_retx(i); + + rlc_amd_retx_t& retx = retx_queue.push(); + srsran_expect(tx_window[nack_sn].rlc_sn == nack_sn, + "Incorrect RLC SN=%d!=%d being accessed", + tx_window[nack_sn].rlc_sn, + nack_sn); + retx.sn = nack_sn; + retx.is_segment = false; + retx.so_start = 0; + retx.so_end = pdu.buf->N_bytes; + } + } + } + }*/ + + /** + * Section 5.3.3.3: Reception of a STATUS report + * - if the STATUS report comprises a positive or negative acknowledgement for the RLC SDU with sequence + * number equal to POLL_SN: + * - if t-PollRetransmit is running: + * - stop and reset t-PollRetransmit. + */ +} uint32_t rlc_am_nr_tx::get_buffer_state() { @@ -351,8 +400,8 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes) // Update RX_Highest_Status /* * - if x = RX_Highest_Status, - * - update RX_Highest_Status to the SN of the first RLC SDU with SN > current RX_Highest_Status for which not all - * bytes have been received. + * - update RX_Highest_Status to the SN of the first RLC SDU with SN > current RX_Highest_Status for which not + * all bytes have been received. */ if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) { uint32_t sn_upd = 0;