diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 6bad2a2cb..50835089a 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -467,6 +467,17 @@ void rlc_um::reassemble_rx_sdus() for(uint32_t i=0; iN_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { + log->warning("Dropping PDU %d due to lost start segment\n", vr_ur); + // Advance data pointers and continue with next segment + rx_window[vr_ur].buf->msg += len; + rx_window[vr_ur].buf->N_bytes -= len; + rx_sdu->reset(); + break; + } + memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); rx_sdu->N_bytes += len; rx_window[vr_ur].buf->msg += len; @@ -488,27 +499,30 @@ void rlc_um::reassemble_rx_sdus() } // Handle last segment - memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes); - rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes; - log->debug("Writting last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n", - vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); - vr_ur_in_rx_sdu = vr_ur; - if(rlc_um_end_aligned(rx_window[vr_ur].header.fi)) - { - if(pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { - log->warning("Dropping remainder of lost PDU (lower edge last segments)\n"); - rx_sdu->reset(); - } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); - rx_sdu->set_timestamp(); - pdcp->write_pdu(lcid, rx_sdu); - rx_sdu = pool_allocate; - if (!rx_sdu) { - log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n"); - return; + if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { + log->debug("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n", + vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); + + memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes); + rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes; + vr_ur_in_rx_sdu = vr_ur; + if(rlc_um_end_aligned(rx_window[vr_ur].header.fi)) + { + if(pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { + log->warning("Dropping remainder of lost PDU (lower edge last segments)\n"); + rx_sdu->reset(); + } else { + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); + rx_sdu->set_timestamp(); + pdcp->write_pdu(lcid, rx_sdu); + rx_sdu = pool_allocate; + if (!rx_sdu) { + log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n"); + return; + } } + pdu_lost = false; } - pdu_lost = false; } // Clean up rx_window @@ -527,10 +541,21 @@ void rlc_um::reassemble_rx_sdus() for(uint32_t i=0; imsg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); + + // Check if the first part of the PDU is a middle or end segment + if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { + log->warning("Dropping PDU %d due to lost start segment\n", vr_ur); + // Advance data pointers and continue with next segment + rx_window[vr_ur].buf->msg += len; + rx_window[vr_ur].buf->N_bytes -= len; + rx_sdu->reset(); + break; + } + log->debug("Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", len, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur_in_rx_sdu, vr_ur, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod); - rx_sdu->N_bytes += len; + memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); + rx_sdu->N_bytes += len; rx_window[vr_ur].buf->msg += len; rx_window[vr_ur].buf->N_bytes -= len; if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%cfg.rx_mod))) { @@ -548,8 +573,14 @@ void rlc_um::reassemble_rx_sdus() } pdu_lost = false; } - + // Handle last segment + if (rx_sdu->N_bytes == 0 && rx_window[vr_ur].header.N_li == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { + log->warning("Dropping PDU %d due to lost start segment\n", vr_ur); + rx_sdu->reset(); + goto clean_up_rx_window; + } + if (rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES && rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES && rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) @@ -557,7 +588,7 @@ void rlc_um::reassemble_rx_sdus() memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes); rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes; - log->debug("Writting last segment in SDU buffer. Updating vr_ur=%d, Buffer size=%d, segment size=%d\n", + log->debug("Writing last segment in SDU buffer. Updating vr_ur=%d, Buffer size=%d, segment size=%d\n", vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); } else { log->error("Out of bounds while reassembling SDU buffer in UM: sdu_len=%d, window_buffer_len=%d, vr_ur=%d\n", @@ -582,6 +613,8 @@ void rlc_um::reassemble_rx_sdus() pdu_lost = false; } +clean_up_rx_window: + // Clean up rx_window pool->deallocate(rx_window[vr_ur].buf); rx_window.erase(vr_ur);