lib,rlc_am_nr: detect gaps in sequence of received SDU segments

This is required for checks such as
"there is at least one missing byte segment [...] before
the last byte of all received segments of this SDU"
master
Robert Falkenberg 3 years ago
parent 51006bbab8
commit d8cb4ec700

@ -230,7 +230,12 @@ public:
bool inside_rx_window(uint32_t sn);
void write_to_upper_layers(uint32_t lcid, unique_byte_buffer_t sdu);
void insert_received_segment(rlc_amd_rx_pdu_nr segment, rlc_amd_rx_sdu_nr_t::segment_list_t& segment_list) const;
bool have_all_segments_been_received(const rlc_amd_rx_sdu_nr_t::segment_list_t& segment_list) const;
/**
* @brief update_segment_inventory This function updates the flags has_gap and fully_received of an SDU
* according to the current inventory of received SDU segments
* @param rx_sdu The SDU to operate on
*/
void update_segment_inventory(rlc_amd_rx_sdu_nr_t& rx_sdu) const;
// Metrics
uint32_t get_sdu_rx_latency_ms() final;

@ -61,6 +61,7 @@ struct rlc_amd_rx_pdu_nr_cmp {
struct rlc_amd_rx_sdu_nr_t {
uint32_t rlc_sn = 0;
bool fully_received = false;
bool has_gap = false;
unique_byte_buffer_t buf;
using segment_list_t = std::set<rlc_amd_rx_pdu_nr, rlc_amd_rx_pdu_nr_cmp>;
segment_list_t segments;

@ -1255,6 +1255,7 @@ int rlc_am_nr_rx::handle_full_data_sdu(const rlc_am_nr_pdu_header_t& header, con
memcpy(rx_sdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header
rx_sdu.buf->N_bytes = nof_bytes - hdr_len;
rx_sdu.fully_received = true;
rx_sdu.has_gap = false;
return SRSRAN_SUCCESS;
}
@ -1296,7 +1297,7 @@ int rlc_am_nr_rx::handle_segment_data_sdu(const rlc_am_nr_pdu_header_t& header,
insert_received_segment(std::move(pdu_segment), rx_sdu.segments);
// Check weather all segments have been received
rx_sdu.fully_received = have_all_segments_been_received(rx_sdu.segments);
update_segment_inventory(rx_sdu);
if (rx_sdu.fully_received) {
RlcInfo("Fully received segmented SDU. SN=%d.", header.sn);
rx_sdu.buf = srsran::make_byte_buffer();
@ -1305,6 +1306,7 @@ int rlc_am_nr_rx::handle_segment_data_sdu(const rlc_am_nr_pdu_header_t& header,
rx_window->remove_pdu(header.sn);
return SRSRAN_ERROR;
}
// Assemble SDU from segments
for (const auto& it : rx_sdu.segments) {
memcpy(&rx_sdu.buf->msg[rx_sdu.buf->N_bytes], it.buf->msg, it.buf->N_bytes);
rx_sdu.buf->N_bytes += it.buf->N_bytes;
@ -1515,27 +1517,34 @@ void rlc_am_nr_rx::insert_received_segment(rlc_amd_rx_pdu_nr
segment_list.insert(std::move(segment));
}
bool rlc_am_nr_rx::have_all_segments_been_received(
const std::set<rlc_amd_rx_pdu_nr, rlc_amd_rx_pdu_nr_cmp>& segment_list) const
void rlc_am_nr_rx::update_segment_inventory(rlc_amd_rx_sdu_nr_t& rx_sdu) const
{
if (segment_list.empty()) {
return false;
}
// Check if we have received the last segment
if (segment_list.rbegin()->header.si != rlc_nr_si_field_t::last_segment) {
return false;
if (rx_sdu.segments.empty()) {
rx_sdu.fully_received = false;
rx_sdu.has_gap = false;
return;
}
// Check if all segments have been received
// Check for gaps and if all segments have been received
uint32_t next_byte = 0;
for (const auto& it : segment_list) {
for (const auto& it : rx_sdu.segments) {
if (it.header.so != next_byte) {
return false;
// Found gap: set flags and return
rx_sdu.has_gap = true;
rx_sdu.fully_received = false;
return;
}
if (it.header.si == rlc_nr_si_field_t::last_segment) {
// Reached last segment without any gaps: set flags and return
rx_sdu.has_gap = false;
rx_sdu.fully_received = true;
return;
}
next_byte += it.buf->N_bytes;
}
return true;
// No gaps, but last segment not yet received
rx_sdu.has_gap = false;
rx_sdu.fully_received = false;
}
/*

Loading…
Cancel
Save