fix bug in RLC UM where lost start segments where not detected

master
Andre Puschmann 7 years ago
parent 60a9e5d756
commit fbc373e13c

@ -467,6 +467,17 @@ void rlc_um::reassemble_rx_sdus()
for(uint32_t i=0; i<rx_window[vr_ur].header.N_li; i++)
{
int len = rx_window[vr_ur].header.li[i];
// Check if we received 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;
}
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; i<rx_window[vr_ur].header.N_li; i++)
{
int len = rx_window[vr_ur].header.li[i];
memcpy(&rx_sdu->msg[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);

Loading…
Cancel
Save