diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index 3cb6845b1..0f042ab73 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -110,10 +110,6 @@ public: uint32_t build_retx_pdu(uint8_t* payload, uint32_t nof_bytes); uint32_t build_retx_pdu_without_segmentation(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); uint32_t build_retx_pdu_with_segmentation(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); - uint32_t build_retx_pdu_from_full_sdu(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); - uint32_t build_retx_segment_from_full_sdu(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); - uint32_t build_retx_pdu_from_sdu_segment(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); - uint32_t build_retx_segment_from_sdu_segment(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes); bool is_retx_segmentation_required(const rlc_amd_retx_t& retx, uint32_t nof_bytes); uint32_t get_retx_expected_hdr_len(const rlc_amd_retx_t& retx); /* diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index 6fd9404ae..62ffa9958 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -629,354 +629,6 @@ uint32_t rlc_am_nr_tx::build_retx_pdu_with_segmentation(rlc_amd_retx_t& retx, ui // TODO return hdr_len + retx_pdu_payload_size; } -/** - * Builds a retx RLC PDU from a full SDU. - * - * The RETX of the full SDU may be further segmented if necessary. - * - * \param [tx_pdu] is the tx_pdu info contained in the tx_window. - * \param [payload] is a pointer to the MAC buffer that will hold the PDU segment. - * \param [nof_bytes] is the number of bytes the RLC is allowed to fill. - * - * \returns the number of bytes written to the payload buffer. - * \remark: This functions assumes that the SDU has already been copied to tx_pdu.sdu_buf. - */ -uint32_t rlc_am_nr_tx::build_retx_pdu_from_full_sdu(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes) -{ - srsran_assert(tx_window.has_sn(retx.sn), "Called %s without checking retx SN", __FUNCTION__); - - // Get tx_pdu info from tx_window - rlc_amd_tx_pdu_nr& tx_pdu = tx_window[retx.sn]; - // Update & write header - rlc_am_nr_pdu_header_t new_header = tx_pdu.header; - new_header.p = 0; - uint32_t hdr_len = rlc_am_nr_write_data_pdu_header(new_header, payload); - - // Check if we exceed allocated number of bytes - if (hdr_len + tx_window[retx.sn].sdu_buf->N_bytes > nof_bytes) { - RlcInfo("Trying to segment retx PDU. SN=%d", retx.sn); - log_rlc_am_nr_pdu_header_to_string(logger.debug, new_header); - return build_retx_segment_from_full_sdu(retx, payload, nof_bytes); - } - - // RETX full PDU - memcpy(&payload[hdr_len], tx_window[retx.sn].sdu_buf->msg, tx_window[retx.sn].sdu_buf->N_bytes); - uint32_t pdu_bytes = hdr_len + tx_window[retx.sn].sdu_buf->N_bytes; - - retx_queue.pop(); - RlcHexInfo(tx_window[retx.sn].sdu_buf->msg, - tx_window[retx.sn].sdu_buf->N_bytes, - "Original SDU SN=%d (%d B) (attempt %d/%d)", - retx.sn, - tx_window[retx.sn].sdu_buf->N_bytes, - tx_window[retx.sn].retx_count + 1, - cfg.max_retx_thresh); - RlcHexInfo(payload, pdu_bytes, "retx PDU SN=%d (%d B)", retx.sn, pdu_bytes); - log_rlc_am_nr_pdu_header_to_string(logger.debug, new_header); - - debug_state(); - return pdu_bytes; -} - -/** - * Builds a retx RLC PDU from a full SDU. - * - * This function will further segment the previously transmitted SDU. - * There should not be enough bytes granted to transmit the previous - * SDU full; this should have been checked previous to calling this - * function. - * - * \param [tx_pdu] is the tx_pdu info contained in the tx_window. - * \param [payload] is a pointer to the MAC buffer that will hold the PDU segment. - * \param [nof_bytes] is the number of bytes the RLC is allowed to fill. - * - * \returns the number of bytes written to the payload buffer. - * \remark: This functions assumes that the SDU has already been copied to tx_pdu.sdu_buf. - */ -uint32_t rlc_am_nr_tx::build_retx_segment_from_full_sdu(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes) -{ - // Get tx_pdu info from tx_window - srsran_assert(tx_window.has_sn(retx.sn), "Called %s without checking retx SN", __FUNCTION__); - rlc_amd_tx_pdu_nr& tx_pdu = tx_window[retx.sn]; - - RlcInfo("creating SDU segment from full SDU. Tx SDU (%d B), nof_bytes=%d B ", tx_pdu.sdu_buf->N_bytes, nof_bytes); - - // Sanity check: is this an SDU segment retx? - if (retx.is_segment) { - RlcError("called %s, but retx contains a SDU segment. SN=%d, current_so=%d, so_start=%d, so_end=%d", - __FUNCTION__, - retx.sn, - retx.current_so, - retx.so_start, - retx.so_end); - return 0; - } - - // Sanity check: are there enough bytes for header plus data? - if (nof_bytes <= min_hdr_size) { - RlcError("called %s, but there are not enough bytes for data plus header. SN=%d", __FUNCTION__, retx.sn); - return 0; - } - - // Sanity check: could this have been transmitted without segmentation? - if (nof_bytes > (tx_pdu.sdu_buf->N_bytes + min_hdr_size)) { - RlcError("called %s, but there are enough bytes to avoid segmentation. SN=%d", __FUNCTION__, retx.sn); - return 0; - } - - // Can the RETX PDU be transmitted in a single PDU? - uint32_t retx_pdu_payload_size = nof_bytes - min_hdr_size; - - // Write header - rlc_am_nr_pdu_header_t hdr = tx_pdu.header; - hdr.si = rlc_nr_si_field_t::first_segment; - uint32_t hdr_len = rlc_am_nr_write_data_pdu_header(hdr, payload); - if (hdr_len >= nof_bytes || hdr_len != min_hdr_size) { - RlcError("error writing AMD PDU header"); - return 0; - } - log_rlc_am_nr_pdu_header_to_string(logger.info, hdr); - - // Copy PDU to payload - srsran_assert((hdr_len + retx_pdu_payload_size) <= nof_bytes, "Error calculating hdr_len and segment_payload_len"); - memcpy(&payload[hdr_len], tx_pdu.sdu_buf->msg, retx_pdu_payload_size); - - // Store Segment Info - rlc_amd_tx_pdu_nr::pdu_segment segment_info; - segment_info.payload_len = retx_pdu_payload_size; - tx_pdu.segment_list.push_back(segment_info); - - // Update retx queue. Next SDU segment will be the rest of the PDU - retx.is_segment = true; - retx.current_so = retx_pdu_payload_size; - - RlcDebug("Updated RETX info. is_segment=%s, current_so=%d, so_start=%d, so_end=%d", - retx.is_segment ? "true" : "false", - retx.current_so, - retx.so_start, - retx.so_end); - - return hdr_len + retx_pdu_payload_size; -} - -/** - * Builds a retx RLC PDU from an RETX SDU segment. - * - * The - * \param [tx_pdu] is the tx_pdu info contained in the tx_window. - * \param [payload] is a pointer to the MAC buffer that will hold the PDU segment. - * \param [nof_bytes] is the number of bytes the RLC is allowed to fill. - * - * \returns the number of bytes written to the payload buffer. - * \remark: This functions assumes that the SDU has already been copied to tx_pdu.sdu_buf. - */ -uint32_t rlc_am_nr_tx::build_retx_pdu_from_sdu_segment(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes) -{ - // Get tx_pdu info from tx_window - srsran_assert(tx_window.has_sn(retx.sn), "Called %s without checking retx SN", __FUNCTION__); - rlc_amd_tx_pdu_nr& tx_pdu = tx_window[retx.sn]; - - RlcInfo("Creating RETX PDU from SDU segment. Tx SDU (%d B), nof_bytes=%d B ", tx_pdu.sdu_buf->N_bytes, nof_bytes); - - // Sanity check: is this an SDU segment retx? - if (not retx.is_segment) { - RlcError("Called %s, but retx contains a SDU segment. SN=%d, current_so=%d, so_start=%d, current_so=%d, so_end=%d", - __FUNCTION__, - retx.sn, - retx.current_so, - retx.so_start, - retx.current_so, - retx.so_end); - return 0; - } - - uint32_t expected_hdr_len = min_hdr_size; - rlc_nr_si_field_t si = rlc_nr_si_field_t::first_segment; - if (retx.current_so != 0) { - si = rlc_nr_si_field_t::neither_first_nor_last_segment; - expected_hdr_len = max_hdr_size; - } - - // Sanity check: are there enough bytes for header plus data? - if (nof_bytes <= expected_hdr_len) { - RlcError("Called %s, but there are not enough bytes for data plus header. SN=%d, nof_bytes=%d, expected_hdr_len=%d", - __FUNCTION__, - retx.sn, - nof_bytes, - expected_hdr_len); - return 0; - } - - // Can be transmitted without segmentation? - if (nof_bytes < (retx.so_end - retx.current_so) + expected_hdr_len) { - RlcDebug("It is necessary to further segment the SDU segment. SN=%d, nof_bytes=%d, expected_hdr_len=%d, " - "current_so=%d, so_start=%d, so_end=%d", - retx.sn, - nof_bytes, - expected_hdr_len, - retx.current_so, - retx.so_start, - retx.so_end); - return build_retx_segment_from_sdu_segment(retx, payload, nof_bytes); - } else { - RlcDebug("SDU segment can be fully transmitted. SN=%d, nof_bytes=%d, expected_hdr_len=%d, " - "current_so=%d, so_start=%d, so_end=%d", - retx.sn, - nof_bytes, - expected_hdr_len, - retx.current_so, - retx.so_start, - retx.so_end); - si = rlc_nr_si_field_t::last_segment; - } - - uint32_t retx_pdu_payload_size = (retx.so_end - retx.current_so); - - // Write header - rlc_am_nr_pdu_header_t hdr = tx_pdu.header; - hdr.si = si; - hdr.so = retx.current_so; - uint32_t hdr_len = rlc_am_nr_write_data_pdu_header(hdr, payload); - if (hdr_len >= nof_bytes || hdr_len != expected_hdr_len) { - RlcError("Error writing AMD PDU header. nof_bytes=%d, hdr_len=%d", nof_bytes, hdr_len); - return 0; - } - log_rlc_am_nr_pdu_header_to_string(logger.info, hdr); - - // Copy SDU segment into payload - srsran_assert((hdr_len + retx_pdu_payload_size) <= nof_bytes, "Error calculating hdr_len and segment_payload_len"); - memcpy(&payload[hdr_len], tx_pdu.sdu_buf->msg, retx_pdu_payload_size); - - // Update retx queue - retx.current_so = retx.current_so + retx_pdu_payload_size; - - RlcDebug("Updated RETX info. is_segment=%s, current_so=%d, so_start=%d, so_end=%d", - retx.is_segment ? "true" : "false", - retx.current_so, - retx.so_start, - retx.so_end); - - if (retx.current_so == tx_pdu.sdu_buf->N_bytes) { - // Last segment to retx, remove retx from queue - retx_queue.pop(); - } else if (retx.current_so > tx_pdu.sdu_buf->N_bytes) { - RlcError("Current SO larger than SDU size. SO_end=%d", retx.so_end); - } - - if (retx.current_so > retx.so_end) { - RlcError("SO end larger than SO start. current_so=%d, SO_start=%d, SO_end=%d", - retx.current_so, - retx.so_start, - retx.so_end); - return 0; - } - - // Update SDU segment info - // TODO - return hdr_len + retx_pdu_payload_size; -} - -/** - * Builds a retx RLC PDU from an SDU SDU segment. - * - * \param [tx_pdu] is the tx_pdu info contained in the tx_window. - * \param [payload] is a pointer to the MAC buffer that will hold the PDU segment. - * \param [nof_bytes] is the number of bytes the RLC is allowed to fill. - * - * \returns the number of bytes written to the payload buffer. - * \remark: This functions assumes that the SDU has already been copied to tx_pdu.sdu_buf. - */ -uint32_t rlc_am_nr_tx::build_retx_segment_from_sdu_segment(rlc_amd_retx_t& retx, uint8_t* payload, uint32_t nof_bytes) -{ - // Get tx_pdu info from tx_window - srsran_assert(tx_window.has_sn(retx.sn), "Called %s without checking retx SN", __FUNCTION__); - rlc_amd_tx_pdu_nr& tx_pdu = tx_window[retx.sn]; - - RlcDebug("Creating SDU segment from SDU segment. Tx SDU (%d B), nof_bytes=%d B ", tx_pdu.sdu_buf->N_bytes, nof_bytes); - - // Sanity check: is this an SDU segment retx? - if (not retx.is_segment) { - RlcError("called %s, but retx contains a SDU segment. SN=%d, current_so=%d, so_start=%d, so_end=%d", - __FUNCTION__, - retx.sn, - retx.current_so, - retx.so_start, - retx.so_end); - return 0; - } - - uint32_t expected_hdr_len = min_hdr_size; - rlc_nr_si_field_t si = rlc_nr_si_field_t::first_segment; - if (retx.current_so != 0) { - si = rlc_nr_si_field_t::neither_first_nor_last_segment; - expected_hdr_len = max_hdr_size; - } - - // Sanity check: are there enough bytes for header plus data? - if (nof_bytes <= expected_hdr_len) { - RlcError("called %s, but there are not enough bytes for data plus header. SN=%d", __FUNCTION__, retx.sn); - return 0; - } - - // Sanity check: could this have been transmitted without segmentation? - if (nof_bytes > (tx_pdu.sdu_buf->N_bytes + expected_hdr_len)) { - RlcError("called %s, but there are enough bytes to avoid segmentation. SN=%d", __FUNCTION__, retx.sn); - return 0; - } - - // Can the RETX PDU be transmitted in a single PDU? - uint32_t retx_pdu_payload_size = nof_bytes - expected_hdr_len; - - // Write header - rlc_am_nr_pdu_header_t hdr = tx_pdu.header; - hdr.so = retx.current_so; - hdr.si = si; - uint32_t hdr_len = rlc_am_nr_write_data_pdu_header(hdr, payload); - if (hdr_len >= nof_bytes || hdr_len != expected_hdr_len) { - log_rlc_am_nr_pdu_header_to_string(logger.error, hdr); - RlcError("Error writing AMD PDU header. nof_bytes=%d, hdr_len=%d", nof_bytes, hdr_len); - return 0; - } - log_rlc_am_nr_pdu_header_to_string(logger.info, hdr); - - // Copy SDU segment into payload - srsran_assert((hdr_len + retx_pdu_payload_size) <= nof_bytes, "Error calculating hdr_len and segment_payload_len"); - memcpy(&payload[hdr_len], tx_pdu.sdu_buf->msg, retx_pdu_payload_size); - - // Update retx queue - retx.current_so = retx.current_so + retx_pdu_payload_size; - - RlcDebug("Updated RETX info. is_segment=%s, current_so=%d, so_start=%d, so_end=%d", - retx.is_segment ? "true" : "false", - retx.current_so, - retx.so_start, - retx.so_end); - - if (retx.current_so >= tx_pdu.sdu_buf->N_bytes) { - RlcError("Current SO larger or equal to SDU size when creating SDU segment. SN=%d, current SO=%d, SO_start=%d, " - "SO_end=%d", - retx.sn, - retx.current_so, - retx.so_start, - retx.so_end); - return 0; - } - - if (retx.current_so >= retx.so_end) { - RlcError("Current SO larger than SO end. SN=%d, current SO=%d, SO_start=%d, SO_end=%s", - retx.sn, - retx.current_so, - retx.so_start, - retx.so_end); - return 0; - } - - // Update SDU segment info - // TODO - return hdr_len + retx_pdu_payload_size; - - return 0; -} bool rlc_am_nr_tx::is_retx_segmentation_required(const rlc_amd_retx_t& retx, uint32_t nof_bytes) {